Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e9ab19fc0 | ||
|
|
4d634d8fa5 | ||
|
|
a538282e4f | ||
|
|
df31921954 | ||
|
|
299abb7b04 | ||
|
|
85ce63b4d3 | ||
|
|
9d9ae288bd | ||
|
|
c0a35eb5e7 | ||
|
|
d1d0ff062b | ||
|
|
396e8a22c4 | ||
|
|
4f040db1ef | ||
|
|
e3cf111344 | ||
|
|
28cb3c383d | ||
|
|
10665c0f37 | ||
|
|
4096f11909 | ||
|
|
5df209b6d5 | ||
|
|
db353fe025 | ||
|
|
30c3e143b8 | ||
|
|
15fe7b33a4 | ||
|
|
17e0666ba4 | ||
|
|
3f24bfaaf5 | ||
|
|
ceadcfece9 | ||
|
|
bc706237ef | ||
|
|
b8c5a78f2e | ||
|
|
9ad1c3a3c8 | ||
|
|
8cfde43f5d | ||
|
|
6f843b071a | ||
|
|
a72b025900 | ||
|
|
dfb66775d7 | ||
|
|
c4dca2df30 | ||
|
|
a3525bdaa4 | ||
|
|
09390bbb97 | ||
|
|
70ae4391d7 | ||
|
|
85931f55e1 |
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/apps"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
@@ -19,7 +20,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := apps.NewAppCmd().
|
||||
var app = apps.NewAppCmd().
|
||||
Version(teaconst.Version).
|
||||
Product(teaconst.ProductName).
|
||||
Usage(teaconst.ProcessName + " [-v|start|stop|restart|status|quit|test|reload|service|daemon|pprof|accesslog]").
|
||||
@@ -67,24 +68,30 @@ func main() {
|
||||
fmt.Println("done")
|
||||
})
|
||||
app.On("pprof", func() {
|
||||
// TODO 自己指定端口
|
||||
addr := "127.0.0.1:6060"
|
||||
var flagSet = flag.NewFlagSet("pprof", flag.ExitOnError)
|
||||
var addr string
|
||||
flagSet.StringVar(&addr, "addr", "", "")
|
||||
_ = flagSet.Parse(os.Args[2:])
|
||||
|
||||
if len(addr) == 0 {
|
||||
addr = "127.0.0.1:6060"
|
||||
}
|
||||
logs.Println("starting with pprof '" + addr + "'...")
|
||||
|
||||
go func() {
|
||||
err := http.ListenAndServe(addr, nil)
|
||||
if err != nil {
|
||||
logs.Println("[error]" + err.Error())
|
||||
logs.Println("[ERROR]" + err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
node := nodes.NewNode()
|
||||
var node = nodes.NewNode()
|
||||
node.Start()
|
||||
})
|
||||
app.On("dbstat", func() {
|
||||
teaconst.EnableDBStat = true
|
||||
|
||||
node := nodes.NewNode()
|
||||
var node = nodes.NewNode()
|
||||
node.Start()
|
||||
})
|
||||
app.On("trackers", func() {
|
||||
@@ -154,7 +161,7 @@ func main() {
|
||||
app.On("ip.drop", func() {
|
||||
var args = os.Args[2:]
|
||||
if len(args) == 0 {
|
||||
fmt.Println("Usage: edge-node ip.drop IP [--timeout=SECONDS]")
|
||||
fmt.Println("Usage: edge-node ip.drop IP [--timeout=SECONDS] [--async]")
|
||||
return
|
||||
}
|
||||
var ip = args[0]
|
||||
@@ -168,6 +175,11 @@ func main() {
|
||||
if ok {
|
||||
timeoutSeconds = types.Int(timeout[0])
|
||||
}
|
||||
var async = false
|
||||
_, ok = options["async"]
|
||||
if ok {
|
||||
async = true
|
||||
}
|
||||
|
||||
fmt.Println("drop ip '" + ip + "' for '" + types.String(timeoutSeconds) + "' seconds")
|
||||
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||
@@ -176,6 +188,7 @@ func main() {
|
||||
Params: map[string]interface{}{
|
||||
"ip": ip,
|
||||
"timeoutSeconds": timeoutSeconds,
|
||||
"async": async,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -306,7 +319,7 @@ func main() {
|
||||
}
|
||||
})
|
||||
app.Run(func() {
|
||||
node := nodes.NewNode()
|
||||
var node = nodes.NewNode()
|
||||
node.Start()
|
||||
})
|
||||
}
|
||||
|
||||
15
go.mod
15
go.mod
@@ -4,6 +4,7 @@ go 1.18
|
||||
|
||||
replace (
|
||||
github.com/TeaOSLab/EdgeCommon => ../EdgeCommon
|
||||
github.com/fsnotify/fsnotify => github.com/iwind/fsnotify v1.5.2-0.20220817040843-193be2051ff4
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -16,10 +17,10 @@ require (
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/google/nftables v0.0.0-20220407195405-950e408d48c6
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475
|
||||
github.com/iwind/TeaGo v0.0.0-20220807030847-31de8e1cbe55
|
||||
github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4
|
||||
github.com/iwind/gowebp v0.0.0-20211029040624-7331ecc78ed8
|
||||
github.com/iwind/gowebp v0.0.0-20220808073410-ac25a4258cf3
|
||||
github.com/klauspost/compress v1.15.8
|
||||
github.com/mattn/go-sqlite3 v1.14.9
|
||||
github.com/mdlayher/netlink v1.4.2
|
||||
@@ -27,20 +28,22 @@ require (
|
||||
github.com/mssola/user_agent v0.5.3
|
||||
github.com/pires/go-proxyproto v0.6.1
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
|
||||
golang.org/x/text v0.3.7
|
||||
google.golang.org/grpc v1.45.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
rogchap.com/v8go v0.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chai2010/webp v1.1.0 // indirect
|
||||
github.com/chai2010/webp v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/google/go-cmp v0.5.7 // indirect
|
||||
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect
|
||||
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect
|
||||
|
||||
84
go.sum
84
go.sum
@@ -1,17 +1,13 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/biessek/golang-ico v0.0.0-20180326222316-d348d9ea4670 h1:FQPKKjDhzG0T4ew6dm6MGrXb4PRAi8ZmTuYuxcF62BM=
|
||||
github.com/biessek/golang-ico v0.0.0-20180326222316-d348d9ea4670/go.mod h1:iRWAFbKXMMkVQyxZ1PfGlkBr1TjATx1zy2MRprV7A3Q=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@@ -20,8 +16,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chai2010/webp v1.1.0 h1:4Ei0/BRroMF9FaXDG2e4OxwFcuW2vcXd+A6tyqTJUQQ=
|
||||
github.com/chai2010/webp v1.1.0/go.mod h1:LP12PG5IFmLGHUU26tBiCBKnghxx3toZFwDjOYvd3Ow=
|
||||
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
|
||||
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
|
||||
github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
@@ -37,7 +33,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200624174652-8d2f3be8b2d9/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -48,10 +43,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
@@ -83,20 +76,20 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/nftables v0.0.0-20220407195405-950e408d48c6 h1:btadZscaRmsi/+fOhkyUguRpSnrf6dykNEWxDeUCj9I=
|
||||
github.com/google/nftables v0.0.0-20220407195405-950e408d48c6/go.mod h1:0F8on3JWMkm+xahTHItkiu/E1SPqMd0TOxNweQv8ptE=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475 h1:EseyfFaQOjWanGiby9KMw7PjDBMg/95tLDgIw/ns0Cw=
|
||||
github.com/iwind/TeaGo v0.0.0-20220304043459-0dd944a5b475/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
|
||||
github.com/iwind/TeaGo v0.0.0-20220807030847-31de8e1cbe55 h1:shQNx0flJFBwKsGE7Hs3bI2bDz+YF0zl/4qE8B2KRiY=
|
||||
github.com/iwind/TeaGo v0.0.0-20220807030847-31de8e1cbe55/go.mod h1:fi/Pq+/5m2HZoseM+39dMF57ANXRt6w4PkGu3NXPc5s=
|
||||
github.com/iwind/fsnotify v1.5.2-0.20220817040843-193be2051ff4 h1:PKtXlgNHJhdwl5ozio7KRV3n0SckMw+8ZC2NCpRSv8U=
|
||||
github.com/iwind/fsnotify v1.5.2-0.20220817040843-193be2051ff4/go.mod h1:DmAukmDY25inGlriLn0B2jidmvaDR1REOcPXwvzvDPI=
|
||||
github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11 h1:DaQjoWZhLNxjhIXedVg4/vFEtHkZhK4IjIwsWdyzBLg=
|
||||
github.com/iwind/gofcgi v0.0.0-20210528023741-a92711d45f11/go.mod h1:JtbX20untAjUVjZs1ZBtq80f5rJWvwtQNRL6EnuYRnY=
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4 h1:VWGsCqTzObdlbf7UUE3oceIpcEKi4C/YBUszQXk118A=
|
||||
github.com/iwind/gosock v0.0.0-20211103081026-ee4652210ca4/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
|
||||
github.com/iwind/gowebp v0.0.0-20211029040624-7331ecc78ed8 h1:AojsHz9Es9B3He2MQQxeRq3TyD//o9huxUo7r1wh44g=
|
||||
github.com/iwind/gowebp v0.0.0-20211029040624-7331ecc78ed8/go.mod h1:QJBY2txYhLMzwLO29iB5ujDJ3s3V7DsZ582nw4Ss+tM=
|
||||
github.com/iwind/gowebp v0.0.0-20220808073410-ac25a4258cf3 h1:2azv4MO3Y4/1bxlx4eLMp/h8Mmq4banSjvgyBpc53Kc=
|
||||
github.com/iwind/gowebp v0.0.0-20220808073410-ac25a4258cf3/go.mod h1:Re7TEhwL+ygnxFg52fC0PWy01ULAIZp2QR0q5WwEOQA=
|
||||
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA=
|
||||
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
@@ -109,14 +102,10 @@ github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20210525051524-4cc836578190/go.mod h1:NmKSdU4VGSiv1bMsdqNALI4RSvvjtz65tTMCnD05qLo=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786 h1:N527AHMa793TP5z5GNAn/VLPzlc0ewzWdeP/25gDfgQ=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20211022192332-93da33804786/go.mod h1:v4hqbTdfQngbVSZJVWUhGE/lbTFf9jb+ygmNUDQMuOs=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e h1:LvL4XsI70QxOGHed6yhQtAU34Kx3Qq2wwBzGFKY8zKk=
|
||||
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.8 h1:JahtItbkWjf2jzm/T+qgMxkP9EMHsqEUA6vCMGmXvhA=
|
||||
github.com/klauspost/compress v1.15.8/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -150,23 +139,11 @@ github.com/mdlayher/socket v0.0.0-20211102153432-57e3fa563ecb h1:2dC7L10LmTqlyMV
|
||||
github.com/mdlayher/socket v0.0.0-20211102153432-57e3fa563ecb/go.mod h1:nFZ1EtZYK8Gi/k6QNu7z7CgO20i/4ExeQswwWuPmG/g=
|
||||
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mssola/user_agent v0.5.3 h1:lBRPML9mdFuIZgI2cmlQ+atbpJdLdeVl2IDodjBR578=
|
||||
github.com/mssola/user_agent v0.5.3/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw=
|
||||
github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -180,9 +157,7 @@ github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtS
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
@@ -196,41 +171,30 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu251/+/jpBpZqir2mPdnU=
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
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/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@@ -259,21 +223,15 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -300,11 +258,10 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -316,7 +273,6 @@ 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.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
@@ -330,7 +286,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg=
|
||||
@@ -339,7 +294,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||
@@ -358,25 +312,19 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=
|
||||
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
rogchap.com/v8go v0.7.0 h1:kgjbiO4zE5itA962ze6Hqmbs4HgZbGzmueCXsZtremg=
|
||||
rogchap.com/v8go v0.7.0/go.mod h1:MxgP3pL2MW4dpme/72QRs8sgNMmM0pRc8DPhcuLWPAs=
|
||||
|
||||
@@ -89,7 +89,10 @@ func (this *LogWriter) Write(message string) {
|
||||
}
|
||||
}
|
||||
|
||||
this.c <- message
|
||||
select {
|
||||
case this.c <- message:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func (this *LogWriter) Close() {
|
||||
|
||||
@@ -227,7 +227,7 @@ func (this *FileList) PurgeLFU(count int, callback func(hash string) error) erro
|
||||
if notFound {
|
||||
_, err = db.deleteHitByHashStmt.Exec(hash)
|
||||
if err != nil {
|
||||
return err
|
||||
return db.WrapError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,14 +359,14 @@ func (this *FileList) remove(hash string) (notFound bool, err error) {
|
||||
|
||||
_, err = db.deleteByHashStmt.Exec(hash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, db.WrapError(err)
|
||||
}
|
||||
|
||||
atomic.AddInt64(&this.total, -1)
|
||||
|
||||
_, err = db.deleteHitByHashStmt.Exec(hash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, db.WrapError(err)
|
||||
}
|
||||
|
||||
if this.onRemove != nil {
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
)
|
||||
|
||||
type FileListDB struct {
|
||||
dbPath string
|
||||
|
||||
readDB *dbs.DB
|
||||
writeDB *dbs.DB
|
||||
|
||||
@@ -49,6 +51,8 @@ func NewFileListDB() *FileListDB {
|
||||
}
|
||||
|
||||
func (this *FileListDB) Open(dbPath string) error {
|
||||
this.dbPath = dbPath
|
||||
|
||||
// write db
|
||||
writeDB, err := sql.Open("sqlite3", "file:"+dbPath+"?cache=private&mode=rwc&_journal_mode=WAL&_sync=OFF&_cache_size=32000&_secure_delete=FAST")
|
||||
if err != nil {
|
||||
@@ -185,7 +189,7 @@ func (this *FileListDB) Add(hash string, item *Item) error {
|
||||
// 放入队列
|
||||
_, err := this.insertStmt.Exec(hash, item.Key, item.HeaderSize, item.BodySize, item.MetaSize, item.ExpiredAt, item.StaleAt, item.Host, item.ServerId, utils.UnixTime())
|
||||
if err != nil {
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -249,7 +253,7 @@ func (this *FileListDB) ListLFUItems(count int) (hashList []string, err error) {
|
||||
func (this *FileListDB) IncreaseHit(hash string) error {
|
||||
var week = timeutil.Format("YW")
|
||||
_, err := this.increaseHitStmt.Exec(hash, week, week, week, week)
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
|
||||
func (this *FileListDB) CleanPrefix(prefix string) error {
|
||||
@@ -262,7 +266,7 @@ func (this *FileListDB) CleanPrefix(prefix string) error {
|
||||
for {
|
||||
result, err := this.writeDB.Exec(`UPDATE "`+this.itemsTableName+`" SET expiredAt=0,staleAt=? WHERE id IN (SELECT id FROM "`+this.itemsTableName+`" WHERE expiredAt>0 AND createdAt<=? AND INSTR("key", ?)=1 LIMIT `+types.String(count)+`)`, unixTime+int64(staleLife), unixTime, prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
affectedRows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
@@ -281,7 +285,7 @@ func (this *FileListDB) CleanAll() error {
|
||||
|
||||
_, err := this.deleteAllStmt.Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -351,6 +355,13 @@ func (this *FileListDB) Close() error {
|
||||
return errors.New("close database failed: " + strings.Join(errStrings, ", "))
|
||||
}
|
||||
|
||||
func (this *FileListDB) WrapError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return errors.New(err.Error() + "(file: " + this.dbPath + ")")
|
||||
}
|
||||
|
||||
// 初始化
|
||||
func (this *FileListDB) initTables(times int) error {
|
||||
{
|
||||
@@ -393,10 +404,10 @@ ON "` + this.itemsTableName + `" (
|
||||
if dropErr == nil {
|
||||
return this.initTables(times + 1)
|
||||
}
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,10 +432,10 @@ ON "` + this.hitsTableName + `" (
|
||||
if dropErr == nil {
|
||||
return this.initTables(times + 1)
|
||||
}
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return this.WrapError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package caches
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// PartialRanges 内容分区范围定义
|
||||
@@ -30,7 +30,7 @@ func NewPartialRangesFromJSON(data []byte) (*PartialRanges, error) {
|
||||
}
|
||||
|
||||
func NewPartialRangesFromFile(path string) (*PartialRanges, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,12 +116,12 @@ func (this *PartialRanges) WriteToFile(path string) error {
|
||||
if err != nil {
|
||||
return errors.New("convert to json failed: " + err.Error())
|
||||
}
|
||||
return ioutil.WriteFile(path, data, 0666)
|
||||
return os.WriteFile(path, data, 0666)
|
||||
}
|
||||
|
||||
// ReadFromFile 从文件中读取
|
||||
func (this *PartialRanges) ReadFromFile(path string) (*PartialRanges, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -65,12 +65,13 @@ var sharedWritingFileKeyLocker = sync.Mutex{}
|
||||
|
||||
var maxOpenFiles = NewMaxOpenFiles()
|
||||
|
||||
const maxOpenFilesSlowCost = 5000 * time.Microsecond // 0.5ms
|
||||
const maxOpenFilesSlowCost = 1000 * time.Microsecond // us
|
||||
const protectingLoadWhenDump = false
|
||||
|
||||
// FileStorage 文件缓存
|
||||
// 文件结构:
|
||||
// [expires time] | [ status ] | [url length] | [header length] | [body length] | [url] [header data] [body data]
|
||||
//
|
||||
// 文件结构:
|
||||
// [expires time] | [ status ] | [url length] | [header length] | [body length] | [url] [header data] [body data]
|
||||
type FileStorage struct {
|
||||
policy *serverconfigs.HTTPCachePolicy
|
||||
options *serverconfigs.HTTPFileCacheStorage // 二级缓存
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@@ -152,7 +152,7 @@ func TestFileStorage_OpenWriter_HTTP(t *testing.T) {
|
||||
"Last-Modified": []string{"Wed, 06 Jan 2021 10:03:29 GMT"},
|
||||
"Server": []string{"CDN-Server"},
|
||||
},
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer([]byte("THIS IS HTTP BODY"))),
|
||||
Body: io.NopCloser(bytes.NewBuffer([]byte("THIS IS HTTP BODY"))),
|
||||
}
|
||||
|
||||
for k, v := range resp.Header {
|
||||
|
||||
@@ -95,7 +95,8 @@ func (this *MemoryStorage) Init() error {
|
||||
// 启动定时Flush memory to disk任务
|
||||
if this.parentStorage != nil {
|
||||
// TODO 应该根据磁盘性能决定线程数
|
||||
var threads = 1
|
||||
// TODO 线程数应该可以在缓存策略和节点中设定
|
||||
var threads = runtime.NumCPU()
|
||||
|
||||
for i := 0; i < threads; i++ {
|
||||
goman.New(func() {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -304,3 +305,30 @@ func TestMemoryStorage_Stop(t *testing.T) {
|
||||
|
||||
t.Log(len(m))
|
||||
}
|
||||
|
||||
func BenchmarkValuesMap(b *testing.B) {
|
||||
var m = map[uint64]*MemoryItem{}
|
||||
var count = 1_000_000
|
||||
for i := 0; i < count; i++ {
|
||||
m[uint64(i)] = &MemoryItem{
|
||||
ExpiresAt: time.Now().Unix(),
|
||||
}
|
||||
}
|
||||
b.Log(len(m))
|
||||
|
||||
var locker = sync.Mutex{}
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
locker.Lock()
|
||||
_, ok := m[uint64(rands.Int(0, 1_000_000))]
|
||||
_ = ok
|
||||
locker.Unlock()
|
||||
|
||||
locker.Lock()
|
||||
delete(m, uint64(rands.Int(2, 1000000)))
|
||||
locker.Unlock()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package caches_test
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/caches"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -16,7 +15,7 @@ func TestPartialFileWriter_Write(t *testing.T) {
|
||||
_ = os.Remove(path)
|
||||
|
||||
var reader = func() {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -10,6 +11,10 @@ import (
|
||||
var sharedBrotliReaderPool *ReaderPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -10,6 +11,10 @@ import (
|
||||
var sharedDeflateReaderPool *ReaderPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -10,6 +11,10 @@ import (
|
||||
var sharedGzipReaderPool *ReaderPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -10,6 +11,10 @@ import (
|
||||
var sharedZSTDReaderPool *ReaderPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -5,10 +5,46 @@ package compressions_test
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/compressions"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBrotliWriter_LargeFile(t *testing.T) {
|
||||
var data = []byte{}
|
||||
for i := 0; i < 1024*1024; i++ {
|
||||
data = append(data, stringutil.Rand(32)...)
|
||||
}
|
||||
t.Log(len(data)/1024/1024, "M")
|
||||
|
||||
var before = time.Now()
|
||||
defer func() {
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
}()
|
||||
|
||||
var buf = &bytes.Buffer{}
|
||||
writer, err := compressions.NewBrotliWriter(buf, 5)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var offset = 0
|
||||
var size = 4096
|
||||
for offset < len(data) {
|
||||
_, err = writer.Write(data[offset : offset+size])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBrotliWriter_Write(b *testing.B) {
|
||||
var data = []byte(strings.Repeat("A", 1024))
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"github.com/andybalholm/brotli"
|
||||
"io"
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
var sharedBrotliWriterPool *WriterPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -4,6 +4,7 @@ package compressions
|
||||
|
||||
import (
|
||||
"compress/flate"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
var sharedDeflateWriterPool *WriterPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -4,6 +4,7 @@ package compressions
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"io"
|
||||
)
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
var sharedGzipWriterPool *WriterPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package compressions
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"github.com/klauspost/compress/zstd"
|
||||
"io"
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
var sharedZSTDWriterPool *WriterPool
|
||||
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
var maxSize = utils.SystemMemoryGB() * 256
|
||||
if maxSize == 0 {
|
||||
maxSize = 256
|
||||
|
||||
@@ -3,7 +3,7 @@ package configs
|
||||
import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// APIConfig 节点API配置
|
||||
@@ -17,7 +17,7 @@ type APIConfig struct {
|
||||
}
|
||||
|
||||
func LoadAPIConfig() (*APIConfig, error) {
|
||||
data, err := ioutil.ReadFile(Tea.ConfigFile("api.yaml"))
|
||||
data, err := os.ReadFile(Tea.ConfigFile("api.yaml"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -37,6 +37,6 @@ func (this *APIConfig) WriteFile(path string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(path, data, 0666)
|
||||
err = os.WriteFile(path, data, 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "0.4.10"
|
||||
Version = "0.5.1"
|
||||
|
||||
ProductName = "Edge Node"
|
||||
ProcessName = "edge-node"
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
package teaconst
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
// 流量统计
|
||||
@@ -12,6 +15,7 @@ var (
|
||||
|
||||
NodeId int64 = 0
|
||||
NodeIdString = ""
|
||||
IsDaemon = len(os.Args) > 1 && os.Args[1] == "daemon"
|
||||
|
||||
GlobalProductName = nodeconfigs.DefaultProductName
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package firewalls
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
@@ -143,7 +144,7 @@ func (this *Firewalld) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *Firewalld) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||
func (this *Firewalld) DropSourceIP(ip string, timeoutSeconds int, async bool) error {
|
||||
if !this.isReady {
|
||||
return nil
|
||||
}
|
||||
@@ -156,7 +157,15 @@ func (this *Firewalld) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
||||
}
|
||||
var cmd = exec.Command(this.exe, args...)
|
||||
this.pushCmd(cmd)
|
||||
if async {
|
||||
this.pushCmd(cmd)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return errors.New("run command failed '" + cmd.String() + "': " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,10 @@ type FirewallInterface interface {
|
||||
RejectSourceIP(ip string, timeoutSeconds int) error
|
||||
|
||||
// DropSourceIP 丢弃某个源IP数据
|
||||
DropSourceIP(ip string, timeoutSeconds int) error
|
||||
// ip 要封禁的IP
|
||||
// timeoutSeconds 过期时间
|
||||
// async 是否异步
|
||||
DropSourceIP(ip string, timeoutSeconds int, async bool) error
|
||||
|
||||
// RemoveSourceIP 删除某个源IP
|
||||
RemoveSourceIP(ip string) error
|
||||
|
||||
@@ -47,7 +47,7 @@ func (this *MockFirewall) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||
}
|
||||
|
||||
// DropSourceIP 丢弃某个源IP数据
|
||||
func (this *MockFirewall) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||
func (this *MockFirewall) DropSourceIP(ip string, timeoutSeconds int, async bool) error {
|
||||
_ = ip
|
||||
_ = timeoutSeconds
|
||||
return nil
|
||||
|
||||
@@ -7,8 +7,10 @@ package firewalls
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/events"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/firewalls/nftables"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net"
|
||||
@@ -21,9 +23,13 @@ import (
|
||||
|
||||
// check nft status, if being enabled we load it automatically
|
||||
func init() {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
var ticker = time.NewTicker(3 * time.Minute)
|
||||
go func() {
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
// if already ready, we break
|
||||
if nftablesIsReady {
|
||||
@@ -48,7 +54,7 @@ func init() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +80,16 @@ func (this *nftablesTableDefinition) protocol() string {
|
||||
return "ip"
|
||||
}
|
||||
|
||||
type blockIPItem struct {
|
||||
action string
|
||||
ip string
|
||||
timeoutSeconds int
|
||||
}
|
||||
|
||||
func NewNFTablesFirewall() (*NFTablesFirewall, error) {
|
||||
var firewall = &NFTablesFirewall{
|
||||
conn: nftables.NewConn(),
|
||||
conn: nftables.NewConn(),
|
||||
dropIPQueue: make(chan *blockIPItem, 4096),
|
||||
}
|
||||
err := firewall.init()
|
||||
if err != nil {
|
||||
@@ -98,6 +111,8 @@ type NFTablesFirewall struct {
|
||||
denyIPv6Set *nftables.Set
|
||||
|
||||
firewalld *Firewalld
|
||||
|
||||
dropIPQueue chan *blockIPItem
|
||||
}
|
||||
|
||||
func (this *NFTablesFirewall) init() error {
|
||||
@@ -243,6 +258,18 @@ func (this *NFTablesFirewall) init() error {
|
||||
nftablesIsReady = true
|
||||
nftablesInstance = this
|
||||
|
||||
goman.New(func() {
|
||||
for ipItem := range this.dropIPQueue {
|
||||
switch ipItem.action {
|
||||
case "drop":
|
||||
err = this.DropSourceIP(ipItem.ip, ipItem.timeoutSeconds, false)
|
||||
if err != nil {
|
||||
remotelogs.Warn("NFTABLES", "drop ip '"+ipItem.ip+"' failed: "+err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// load firewalld
|
||||
var firewalld = NewFirewalld()
|
||||
if firewalld.IsReady() {
|
||||
@@ -307,16 +334,29 @@ func (this *NFTablesFirewall) AllowSourceIP(ip string) error {
|
||||
// RejectSourceIP 拒绝某个源IP连接
|
||||
// we did not create set for drop ip, so we reuse DropSourceIP() method here
|
||||
func (this *NFTablesFirewall) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||
return this.DropSourceIP(ip, timeoutSeconds)
|
||||
return this.DropSourceIP(ip, timeoutSeconds, true)
|
||||
}
|
||||
|
||||
// DropSourceIP 丢弃某个源IP数据
|
||||
func (this *NFTablesFirewall) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||
func (this *NFTablesFirewall) DropSourceIP(ip string, timeoutSeconds int, async bool) error {
|
||||
var data = net.ParseIP(ip)
|
||||
if data == nil {
|
||||
return errors.New("invalid ip '" + ip + "'")
|
||||
}
|
||||
|
||||
if async {
|
||||
select {
|
||||
case this.dropIPQueue <- &blockIPItem{
|
||||
action: "drop",
|
||||
ip: ip,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
}:
|
||||
default:
|
||||
return errors.New("drop ip queue is full")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.Contains(ip, ":") { // ipv6
|
||||
if this.denyIPv6Set == nil {
|
||||
return errors.New("ipv6 ip set is nil")
|
||||
|
||||
@@ -51,7 +51,7 @@ func (this *NFTablesFirewall) RejectSourceIP(ip string, timeoutSeconds int) erro
|
||||
}
|
||||
|
||||
// DropSourceIP 丢弃某个源IP数据
|
||||
func (this *NFTablesFirewall) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||
func (this *NFTablesFirewall) DropSourceIP(ip string, timeoutSeconds int, async bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package goman
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -14,6 +15,10 @@ var instanceId = uint64(0)
|
||||
|
||||
// New 新创建goroutine
|
||||
func New(f func()) {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
|
||||
go func() {
|
||||
@@ -42,6 +47,10 @@ func New(f func()) {
|
||||
|
||||
// NewWithArgs 创建带有参数的goroutine
|
||||
func NewWithArgs(f func(args ...interface{}), args ...interface{}) {
|
||||
if teaconst.IsDaemon {
|
||||
return
|
||||
}
|
||||
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -4,7 +4,7 @@ package iplibrary
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -62,7 +62,7 @@ func getIpInfo(cityId int64, line []byte) *IpInfo {
|
||||
|
||||
func NewIP2Region(path string) (*IP2Region, error) {
|
||||
var region = &IP2Region{}
|
||||
region.dbData, err = ioutil.ReadFile(path)
|
||||
region.dbData, err = os.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -106,6 +106,7 @@ func BenchmarkIP2RegionLibrary_Lookup(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = library.Lookup("8.8.8.8")
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -90,7 +89,7 @@ func (this *CityManager) Lookup(provinceId int64, cityName string) (cityId int64
|
||||
|
||||
// 从缓存中读取
|
||||
func (this *CityManager) load() error {
|
||||
data, err := ioutil.ReadFile(this.cacheFile)
|
||||
data, err := os.ReadFile(this.cacheFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
@@ -119,7 +118,7 @@ func (this *CityManager) loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := rpcClient.RegionCityRPC().FindAllEnabledRegionCities(rpcClient.Context(), &pb.FindAllEnabledRegionCitiesRequest{})
|
||||
resp, err := rpcClient.RegionCityRPC().FindAllRegionCities(rpcClient.Context(), &pb.FindAllRegionCitiesRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -151,6 +150,6 @@ func (this *CityManager) loop() error {
|
||||
|
||||
// 保存到本地缓存
|
||||
|
||||
err = ioutil.WriteFile(this.cacheFile, data, 0666)
|
||||
err = os.WriteFile(this.cacheFile, data, 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -89,7 +88,7 @@ func (this *CountryManager) Lookup(countryName string) (countryId int64) {
|
||||
|
||||
// 从缓存中读取
|
||||
func (this *CountryManager) load() error {
|
||||
data, err := ioutil.ReadFile(this.cacheFile)
|
||||
data, err := os.ReadFile(this.cacheFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
@@ -118,7 +117,7 @@ func (this *CountryManager) loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := rpcClient.RegionCountryRPC().FindAllEnabledRegionCountries(rpcClient.Context(), &pb.FindAllEnabledRegionCountriesRequest{})
|
||||
resp, err := rpcClient.RegionCountryRPC().FindAllRegionCountries(rpcClient.Context(), &pb.FindAllRegionCountriesRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -149,6 +148,6 @@ func (this *CountryManager) loop() error {
|
||||
this.locker.Unlock()
|
||||
|
||||
// 保存到本地缓存
|
||||
err = ioutil.WriteFile(this.cacheFile, data, 0666)
|
||||
err = os.WriteFile(this.cacheFile, data, 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -89,7 +88,7 @@ func (this *ProviderManager) Lookup(providerName string) (providerId int64) {
|
||||
|
||||
// 从缓存中读取
|
||||
func (this *ProviderManager) load() error {
|
||||
data, err := ioutil.ReadFile(this.cacheFile)
|
||||
data, err := os.ReadFile(this.cacheFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
@@ -118,7 +117,7 @@ func (this *ProviderManager) loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := rpcClient.RegionProviderRPC().FindAllEnabledRegionProviders(rpcClient.Context(), &pb.FindAllEnabledRegionProvidersRequest{})
|
||||
resp, err := rpcClient.RegionProviderRPC().FindAllRegionProviders(rpcClient.Context(), &pb.FindAllRegionProvidersRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -150,6 +149,6 @@ func (this *ProviderManager) loop() error {
|
||||
|
||||
// 保存到本地缓存
|
||||
|
||||
err = ioutil.WriteFile(this.cacheFile, data, 0666)
|
||||
err = os.WriteFile(this.cacheFile, data, 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -93,7 +92,7 @@ func (this *ProvinceManager) Lookup(provinceName string) (provinceId int64) {
|
||||
|
||||
// 从缓存中读取
|
||||
func (this *ProvinceManager) load() error {
|
||||
data, err := ioutil.ReadFile(this.cacheFile)
|
||||
data, err := os.ReadFile(this.cacheFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
@@ -122,7 +121,7 @@ func (this *ProvinceManager) loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := rpcClient.RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(rpcClient.Context(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
|
||||
resp, err := rpcClient.RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(rpcClient.Context(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||
RegionCountryId: ChinaCountryId,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -156,6 +155,6 @@ func (this *ProvinceManager) loop() error {
|
||||
|
||||
// 保存到本地缓存
|
||||
|
||||
err = ioutil.WriteFile(this.cacheFile, data, 0666)
|
||||
err = os.WriteFile(this.cacheFile, data, 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,18 +23,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const MaxQueueSize = 2048
|
||||
const MaxQueueSize = 256 // TODO 可以配置,可以在单个任务里配置
|
||||
|
||||
// Task 单个指标任务
|
||||
// 数据库存储:
|
||||
// data/
|
||||
// metric.$ID.db
|
||||
// stats
|
||||
// id, keys, value, time, serverId, hash
|
||||
// 原理:
|
||||
// 添加或者有变更时 isUploaded = false
|
||||
// 上传时检查 isUploaded 状态
|
||||
// 只上传每个服务中排序最前面的 N 个数据
|
||||
//
|
||||
// data/
|
||||
// metric.$ID.db
|
||||
// stats
|
||||
// id, keys, value, time, serverId, hash
|
||||
// 原理:
|
||||
// 添加或者有变更时 isUploaded = false
|
||||
// 上传时检查 isUploaded 状态
|
||||
// 只上传每个服务中排序最前面的 N 个数据
|
||||
type Task struct {
|
||||
item *serverconfigs.MetricItemConfig
|
||||
isLoaded bool
|
||||
@@ -372,7 +373,9 @@ func (this *Task) Upload(pauseDuration time.Duration) error {
|
||||
for _, serverId := range serverIds {
|
||||
for _, currentTime := range times {
|
||||
idStrings, err := func(serverId int64, currentTime string) (ids []string, err error) {
|
||||
var t = trackers.Begin("[METRIC]SELECT_TOP_STMT")
|
||||
rows, err := this.selectTopStmt.Query(serverId, this.item.Version, currentTime)
|
||||
t.End()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func (this *ClientListener) Accept() (net.Conn, error) {
|
||||
if beingDenied {
|
||||
var fw = firewalls.Firewall()
|
||||
if fw != nil && !fw.IsMock() {
|
||||
_ = fw.DropSourceIP(ip, 60)
|
||||
_ = fw.DropSourceIP(ip, 120, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -236,7 +235,7 @@ func (this *HTTPCacheTaskManager) fetchKey(key *pb.HTTPCacheTaskKey) error {
|
||||
}()
|
||||
|
||||
// 读取内容,以便于生成缓存
|
||||
_, _ = io.Copy(ioutil.Discard, resp.Body)
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
|
||||
// 处理502
|
||||
if resp.StatusCode == http.StatusBadGateway {
|
||||
|
||||
@@ -54,6 +54,7 @@ func (this *HTTPClientPool) Client(req *HTTPRequest,
|
||||
}
|
||||
|
||||
var key = origin.UniqueKey() + "@" + originAddr
|
||||
var isLnRequest = origin.Id == 0
|
||||
|
||||
this.locker.RLock()
|
||||
client, found := this.clientsMap[key]
|
||||
@@ -101,6 +102,17 @@ func (this *HTTPClientPool) Client(req *HTTPRequest,
|
||||
idleConns = numberCPU * 8
|
||||
}
|
||||
|
||||
// 可以判断为Ln节点请求
|
||||
if isLnRequest {
|
||||
maxConnections *= 8
|
||||
idleConns *= 8
|
||||
idleTimeout *= 4
|
||||
} else if sharedNodeConfig != nil && sharedNodeConfig.Level > 1 {
|
||||
// Ln节点可以适当增加连接数
|
||||
maxConnections *= 2
|
||||
idleConns *= 2
|
||||
}
|
||||
|
||||
// TLS通讯
|
||||
var tlsConfig = &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
@@ -149,6 +161,7 @@ func (this *HTTPClientPool) Client(req *HTTPRequest,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
TLSHandshakeTimeout: 5 * time.Second,
|
||||
TLSClientConfig: tlsConfig,
|
||||
ReadBufferSize: 8 * 1024,
|
||||
Proxy: nil,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestHTTPClientPool_Client(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPClientPool_cleanClients(t *testing.T) {
|
||||
origin := &serverconfigs.OriginConfig{
|
||||
var origin = &serverconfigs.OriginConfig{
|
||||
Id: 1,
|
||||
Version: 2,
|
||||
Addr: &serverconfigs.NetworkAddressConfig{Host: "127.0.0.1", PortRange: "1234"},
|
||||
@@ -48,8 +48,7 @@ func TestHTTPClientPool_cleanClients(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pool := NewHTTPClientPool()
|
||||
pool.clientExpiredDuration = 2 * time.Second
|
||||
var pool = NewHTTPClientPool()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
t.Log("get", i)
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -151,7 +150,7 @@ func (this *HTTPRequest) Do() {
|
||||
// Web配置
|
||||
err := this.configureWeb(this.ReqServer.Web, true, 0)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to configure the server", "配置服务失败", false)
|
||||
this.doEnd()
|
||||
return
|
||||
}
|
||||
@@ -284,12 +283,12 @@ func (this *HTTPRequest) doBegin() {
|
||||
this.web.AccessLogRef.IsOn &&
|
||||
this.web.AccessLogRef.ContainsField(serverconfigs.HTTPAccessLogFieldRequestBody) {
|
||||
var err error
|
||||
this.requestBodyData, err = ioutil.ReadAll(io.LimitReader(this.RawReq.Body, AccessLogMaxRequestBodySize))
|
||||
this.requestBodyData, err = io.ReadAll(io.LimitReader(this.RawReq.Body, AccessLogMaxRequestBodySize))
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusBadGateway, false)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to read request body for access log", "为访问日志读取请求Body失败", false)
|
||||
return
|
||||
}
|
||||
this.RawReq.Body = ioutil.NopCloser(io.MultiReader(bytes.NewBuffer(this.requestBodyData), this.RawReq.Body))
|
||||
this.RawReq.Body = io.NopCloser(io.MultiReader(bytes.NewBuffer(this.requestBodyData), this.RawReq.Body))
|
||||
}
|
||||
|
||||
// 跳转
|
||||
@@ -1390,12 +1389,12 @@ func (this *HTTPRequest) Cookie(name string) string {
|
||||
return c.Value
|
||||
}
|
||||
|
||||
// DeleteHeader 删除Header
|
||||
// DeleteHeader 删除请求Header
|
||||
func (this *HTTPRequest) DeleteHeader(name string) {
|
||||
this.RawReq.Header.Del(name)
|
||||
}
|
||||
|
||||
// SetHeader 设置Header
|
||||
// SetHeader 设置请求Header
|
||||
func (this *HTTPRequest) SetHeader(name string, values []string) {
|
||||
this.RawReq.Header[name] = values
|
||||
}
|
||||
@@ -1712,7 +1711,12 @@ func (this *HTTPRequest) canIgnore(err error) bool {
|
||||
}
|
||||
|
||||
// 客户端主动取消
|
||||
if err == errWritingToClient || err == context.Canceled || err == io.ErrShortWrite || strings.Contains(err.Error(), "write: connection timed out") || strings.Contains(err.Error(), "write: broken pipe") {
|
||||
if err == errWritingToClient ||
|
||||
err == context.Canceled ||
|
||||
err == io.ErrShortWrite ||
|
||||
strings.Contains(err.Error(), "write: connection") ||
|
||||
strings.Contains(err.Error(), "write: broken pipe") ||
|
||||
strings.Contains(err.Error(), "write tcp") {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package nodes
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -26,14 +26,14 @@ func (this *HTTPRequest) doAuth() (shouldStop bool) {
|
||||
subReq.Proto = this.RawReq.Proto
|
||||
subReq.ProtoMinor = this.RawReq.ProtoMinor
|
||||
subReq.ProtoMajor = this.RawReq.ProtoMajor
|
||||
subReq.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||
subReq.Body = io.NopCloser(bytes.NewReader([]byte{}))
|
||||
subReq.Header.Set("Referer", this.URL())
|
||||
var writer = NewEmptyResponseWriter(this.writer)
|
||||
this.doSubRequest(writer, subReq)
|
||||
return writer.StatusCode(), nil
|
||||
}, this.Format)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to execute the AuthPolicy", "认证策略执行失败", false)
|
||||
return
|
||||
}
|
||||
if b {
|
||||
|
||||
@@ -1,32 +1,59 @@
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const httpStatusPageTemplate = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>${status} ${statusMessage}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>${status} ${statusMessage}</h1>
|
||||
<p>${message}</p>
|
||||
|
||||
<address>Request ID: ${requestId}.</address>
|
||||
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
func (this *HTTPRequest) write404() {
|
||||
if this.doPage(http.StatusNotFound) {
|
||||
this.writeCode(http.StatusNotFound)
|
||||
}
|
||||
|
||||
func (this *HTTPRequest) writeCode(statusCode int) {
|
||||
if this.doPage(statusCode) {
|
||||
return
|
||||
}
|
||||
|
||||
this.processResponseHeaders(http.StatusNotFound)
|
||||
this.writer.WriteHeader(http.StatusNotFound)
|
||||
_, _ = this.writer.Write([]byte("404 page not found: '" + this.URL() + "'" + " (Request Id: " + this.requestId + ")"))
|
||||
var pageContent = configutils.ParseVariables(httpStatusPageTemplate, func(varName string) (value string) {
|
||||
switch varName {
|
||||
case "status":
|
||||
return types.String(statusCode)
|
||||
case "statusMessage":
|
||||
return http.StatusText(statusCode)
|
||||
case "requestId":
|
||||
return this.requestId
|
||||
case "message":
|
||||
return "" // 空
|
||||
}
|
||||
return "${" + varName + "}"
|
||||
})
|
||||
|
||||
this.processResponseHeaders(statusCode)
|
||||
this.writer.WriteHeader(statusCode)
|
||||
|
||||
_, _ = this.writer.Write([]byte(pageContent))
|
||||
}
|
||||
|
||||
func (this *HTTPRequest) writeCode(code int) {
|
||||
if this.doPage(code) {
|
||||
return
|
||||
}
|
||||
|
||||
this.processResponseHeaders(code)
|
||||
this.writer.WriteHeader(code)
|
||||
_, _ = this.writer.Write([]byte(types.String(code) + " " + http.StatusText(code) + ": '" + this.URL() + "'" + " (Request Id: " + this.requestId + ")"))
|
||||
}
|
||||
|
||||
func (this *HTTPRequest) write50x(err error, statusCode int, canTryStale bool) {
|
||||
func (this *HTTPRequest) write50x(err error, statusCode int, enMessage string, zhMessage string, canTryStale bool) {
|
||||
if err != nil {
|
||||
this.addError(err)
|
||||
}
|
||||
@@ -37,7 +64,7 @@ func (this *HTTPRequest) write50x(err error, statusCode int, canTryStale bool) {
|
||||
this.web.Cache.Stale != nil &&
|
||||
this.web.Cache.Stale.IsOn &&
|
||||
(len(this.web.Cache.Stale.Status) == 0 || lists.ContainsInt(this.web.Cache.Stale.Status, statusCode)) {
|
||||
ok := this.doCacheRead(true)
|
||||
var ok = this.doCacheRead(true)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
@@ -47,7 +74,34 @@ func (this *HTTPRequest) write50x(err error, statusCode int, canTryStale bool) {
|
||||
if this.doPage(statusCode) {
|
||||
return
|
||||
}
|
||||
|
||||
// 内置HTML模板
|
||||
var pageContent = configutils.ParseVariables(httpStatusPageTemplate, func(varName string) (value string) {
|
||||
switch varName {
|
||||
case "status":
|
||||
return types.String(statusCode)
|
||||
case "statusMessage":
|
||||
return http.StatusText(statusCode)
|
||||
case "requestId":
|
||||
return this.requestId
|
||||
case "message":
|
||||
var acceptLanguages = this.RawReq.Header.Get("Accept-Language")
|
||||
if len(acceptLanguages) > 0 {
|
||||
var index = strings.Index(acceptLanguages, ",")
|
||||
if index > 0 {
|
||||
var firstLanguage = acceptLanguages[:index]
|
||||
if firstLanguage == "zh-CN" {
|
||||
return "网站出了一点小问题,原因:" + zhMessage + "。"
|
||||
}
|
||||
}
|
||||
}
|
||||
return "The site is unavailable now, cause: " + enMessage + "."
|
||||
}
|
||||
return "${" + varName + "}"
|
||||
})
|
||||
|
||||
this.processResponseHeaders(statusCode)
|
||||
this.writer.WriteHeader(statusCode)
|
||||
_, _ = this.writer.Write([]byte(types.String(statusCode) + " " + http.StatusText(statusCode) + " (Request Id: " + this.requestId + ")"))
|
||||
|
||||
_, _ = this.writer.Write([]byte(pageContent))
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func (this *HTTPRequest) doFastcgi() (shouldStop bool) {
|
||||
|
||||
client, err := fcgi.SharedPool(fastcgi.Network(), fastcgi.RealAddress(), uint(poolSize)).Client()
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to create Fastcgi pool", "Fastcgi池生成失败", false)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -159,13 +159,13 @@ func (this *HTTPRequest) doFastcgi() (shouldStop bool) {
|
||||
|
||||
resp, stderr, err := client.Call(fcgiReq)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to read Fastcgi", "读取Fastcgi失败", false)
|
||||
return
|
||||
}
|
||||
|
||||
if len(stderr) > 0 {
|
||||
err := errors.New("Fastcgi Error: " + strings.TrimSpace(string(stderr)) + " script: " + maps.NewMap(params).GetString("SCRIPT_FILENAME"))
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to read Fastcgi", "读取Fastcgi失败", false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ func (this *HTTPRequest) checkLnRequest() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *HTTPRequest) getLnOrigin() *serverconfigs.OriginConfig {
|
||||
return nil
|
||||
func (this *HTTPRequest) getLnOrigin(excludingNodeIds []int64) (originConfig *serverconfigs.OriginConfig, lnNodeId int64, hasMultipleNodes bool) {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
@@ -21,10 +21,32 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
return
|
||||
}
|
||||
|
||||
var retries = 3
|
||||
|
||||
var failedOriginIds []int64
|
||||
var failedLnNodeIds []int64
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
originId, lnNodeId, shouldRetry := this.doOriginRequest(failedOriginIds, failedLnNodeIds, i == 0, i == retries-1)
|
||||
if !shouldRetry {
|
||||
break
|
||||
}
|
||||
if originId > 0 {
|
||||
failedOriginIds = append(failedOriginIds, originId)
|
||||
}
|
||||
if lnNodeId > 0 {
|
||||
failedLnNodeIds = append(failedLnNodeIds, lnNodeId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 请求源站
|
||||
func (this *HTTPRequest) doOriginRequest(failedOriginIds []int64, failedLnNodeIds []int64, isFirstTry bool, isLastRetry bool) (originId int64, lnNodeId int64, shouldRetry bool) {
|
||||
// 对URL的处理
|
||||
var stripPrefix = this.reverseProxy.StripPrefix
|
||||
var requestURI = this.reverseProxy.RequestURI
|
||||
var requestURIHasVariables = this.reverseProxy.RequestURIHasVariables()
|
||||
var oldURI = this.uri
|
||||
|
||||
var requestHost = ""
|
||||
if this.reverseProxy.RequestHostType == serverconfigs.RequestHostTypeCustomized {
|
||||
@@ -41,24 +63,39 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
var origin *serverconfigs.OriginConfig
|
||||
|
||||
// 二级节点
|
||||
var hasMultipleLnNodes = false
|
||||
if this.cacheRef != nil {
|
||||
origin = this.getLnOrigin()
|
||||
origin, lnNodeId, hasMultipleLnNodes = this.getLnOrigin(failedLnNodeIds)
|
||||
if origin != nil {
|
||||
// 强制变更原来访问的域名
|
||||
requestHost = this.ReqHost
|
||||
}
|
||||
|
||||
// 回源Header中去除If-None-Match和If-Modified-Since
|
||||
if !this.cacheRef.EnableIfNoneMatch {
|
||||
this.DeleteHeader("If-None-Match")
|
||||
}
|
||||
if !this.cacheRef.EnableIfModifiedSince {
|
||||
this.DeleteHeader("If-Modified-Since")
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义源站
|
||||
if origin == nil {
|
||||
origin = this.reverseProxy.NextOrigin(requestCall)
|
||||
if !isFirstTry {
|
||||
origin = this.reverseProxy.AnyOrigin(requestCall, failedOriginIds)
|
||||
}
|
||||
if origin == nil {
|
||||
origin = this.reverseProxy.NextOrigin(requestCall)
|
||||
}
|
||||
requestCall.CallResponseCallbacks(this.writer)
|
||||
if origin == nil {
|
||||
err := errors.New(this.URL() + ": no available origin sites for reverse proxy")
|
||||
remotelogs.ServerError(this.ReqServer.Id, "HTTP_REQUEST_REVERSE_PROXY", err.Error(), "", nil)
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "No origin site yet", "尚未配置源站", true)
|
||||
return
|
||||
}
|
||||
originId = origin.Id
|
||||
|
||||
if len(origin.StripPrefix) > 0 {
|
||||
stripPrefix = origin.StripPrefix
|
||||
@@ -80,7 +117,7 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
if origin.Addr == nil {
|
||||
err := errors.New(this.URL() + ": Origin '" + strconv.FormatInt(origin.Id, 10) + "' does not has a address")
|
||||
remotelogs.Error("HTTP_REQUEST_REVERSE_PROXY", err.Error())
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "Origin site did not has a valid address", "源站尚未配置地址", true)
|
||||
return
|
||||
}
|
||||
this.RawReq.URL.Scheme = origin.Addr.Protocol.Primary().Scheme()
|
||||
@@ -132,7 +169,7 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
if originHostIndex < 0 {
|
||||
var originErr = errors.New(this.URL() + ": Invalid origin address '" + originAddr + "', lacking port")
|
||||
remotelogs.Error("HTTP_REQUEST_REVERSE_PROXY", originErr.Error())
|
||||
this.write50x(originErr, http.StatusBadGateway, true)
|
||||
this.write50x(originErr, http.StatusBadGateway, "No port in origin site address", "源站地址中没有配置端口", true)
|
||||
return
|
||||
}
|
||||
originAddr = originAddr[:originHostIndex+1] + types.String(this.requestServerPort())
|
||||
@@ -211,12 +248,12 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
client, err := SharedHTTPClientPool.Client(this, origin, originAddr, this.reverseProxy.ProxyProtocol, this.reverseProxy.FollowRedirects)
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTP_REQUEST_REVERSE_PROXY", this.URL()+": Create client failed: "+err.Error())
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to create origin site client", "构造源站客户端失败", true)
|
||||
return
|
||||
}
|
||||
|
||||
// 在HTTP/2下需要防止因为requestBody而导致Content-Length为空的问题
|
||||
if this.RawReq.ProtoMajor == 2 && this.RawReq.ContentLength == 0 {
|
||||
if this.RawReq.ProtoMajor == 2 && this.RawReq.ContentLength == 0 && this.RawReq.Body != nil {
|
||||
_ = this.RawReq.Body.Close()
|
||||
this.RawReq.Body = nil
|
||||
}
|
||||
@@ -230,18 +267,35 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
SharedOriginStateManager.Fail(origin, requestHost, this.reverseProxy, func() {
|
||||
this.reverseProxy.ResetScheduling()
|
||||
})
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to read origin site", "源站读取失败", true)
|
||||
remotelogs.Warn("HTTP_REQUEST_REVERSE_PROXY", this.RawReq.URL.String()+": Request origin server failed: "+err.Error())
|
||||
} else if httpErr.Err != context.Canceled {
|
||||
SharedOriginStateManager.Fail(origin, requestHost, this.reverseProxy, func() {
|
||||
this.reverseProxy.ResetScheduling()
|
||||
})
|
||||
|
||||
// 是否需要重试
|
||||
if (originId > 0 || (lnNodeId > 0 && hasMultipleLnNodes)) && !isLastRetry {
|
||||
shouldRetry = true
|
||||
this.uri = oldURI // 恢复备份
|
||||
|
||||
if resp != nil && resp.Body != nil {
|
||||
_ = resp.Body.Close()
|
||||
}
|
||||
|
||||
if httpErr.Err != io.EOF {
|
||||
remotelogs.Warn("HTTP_REQUEST_REVERSE_PROXY", this.URL()+": Request origin server failed: "+err.Error())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if httpErr.Timeout() {
|
||||
this.write50x(err, http.StatusGatewayTimeout, true)
|
||||
this.write50x(err, http.StatusGatewayTimeout, "Read origin site timeout", "源站读取超时", true)
|
||||
} else if httpErr.Temporary() {
|
||||
this.write50x(err, http.StatusServiceUnavailable, true)
|
||||
this.write50x(err, http.StatusServiceUnavailable, "Origin site unavailable now", "源站当前不可用", true)
|
||||
} else {
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to read origin site", "源站读取失败", true)
|
||||
}
|
||||
if httpErr.Err != io.EOF {
|
||||
remotelogs.Warn("HTTP_REQUEST_REVERSE_PROXY", this.URL()+": Request origin server failed: "+err.Error())
|
||||
@@ -264,7 +318,7 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
}
|
||||
|
||||
if !isClientError {
|
||||
this.write50x(err, http.StatusBadGateway, true)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to read origin site", "源站读取失败", true)
|
||||
}
|
||||
}
|
||||
if resp != nil && resp.Body != nil {
|
||||
@@ -410,4 +464,6 @@ func (this *HTTPRequest) doReverseProxy() {
|
||||
if (err == nil || err == io.EOF) && (closeErr == nil || closeErr == io.EOF) {
|
||||
this.writer.SetOk()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func (this *HTTPRequest) doRoot() (isBreak bool) {
|
||||
}
|
||||
return
|
||||
} else {
|
||||
this.write50x(err, http.StatusInternalServerError, true)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to stat the file", "查看文件统计信息失败", true)
|
||||
if !this.canIgnore(err) {
|
||||
logs.Error(err)
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (this *HTTPRequest) doRoot() (isBreak bool) {
|
||||
}
|
||||
return
|
||||
} else {
|
||||
this.write50x(err, http.StatusInternalServerError, true)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to stat the file", "查看文件统计信息失败", true)
|
||||
if !this.canIgnore(err) {
|
||||
logs.Error(err)
|
||||
}
|
||||
@@ -285,7 +285,7 @@ func (this *HTTPRequest) doRoot() (isBreak bool) {
|
||||
|
||||
fileReader, err := os.OpenFile(filePath, os.O_RDONLY, 0444)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusInternalServerError, true)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to open the file", "试图打开文件失败", true)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ func (this *HTTPRequest) doURL(method string, url string, host string, statusCod
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
remotelogs.Error("HTTP_REQUEST_URL", req.URL.String()+": "+err.Error())
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to read url", "读取URL失败", false)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -180,14 +180,14 @@ var httpRequestTimestamp int64
|
||||
var httpRequestId int32 = 1_000_000
|
||||
|
||||
func httpRequestNextId() string {
|
||||
var unixTime = utils.UnixTimeMilli()
|
||||
unixTime, unixTimeString := utils.UnixTimeMilliString()
|
||||
if unixTime > httpRequestTimestamp {
|
||||
atomic.StoreInt32(&httpRequestId, 1_000_000)
|
||||
httpRequestTimestamp = unixTime
|
||||
}
|
||||
|
||||
// timestamp + requestId + nodeId
|
||||
return strconv.FormatInt(unixTime, 10) + teaconst.NodeIdString + strconv.Itoa(int(atomic.AddInt32(&httpRequestId, 1)))
|
||||
// timestamp + nodeId + requestId
|
||||
return unixTimeString + teaconst.NodeIdString + strconv.Itoa(int(atomic.AddInt32(&httpRequestId, 1)))
|
||||
}
|
||||
|
||||
// 检查是否可以接受某个编码
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -359,7 +358,7 @@ func (this *HTTPRequest) WAFSetCacheBody(body []byte) {
|
||||
// WAFReadBody 读取Body
|
||||
func (this *HTTPRequest) WAFReadBody(max int64) (data []byte, err error) {
|
||||
if this.RawReq.ContentLength > 0 {
|
||||
data, err = ioutil.ReadAll(io.LimitReader(this.RawReq.Body, max))
|
||||
data, err = io.ReadAll(io.LimitReader(this.RawReq.Body, max))
|
||||
}
|
||||
|
||||
return
|
||||
@@ -368,7 +367,7 @@ func (this *HTTPRequest) WAFReadBody(max int64) (data []byte, err error) {
|
||||
// WAFRestoreBody 恢复Body
|
||||
func (this *HTTPRequest) WAFRestoreBody(data []byte) {
|
||||
if len(data) > 0 {
|
||||
this.RawReq.Body = ioutil.NopCloser(io.MultiReader(bytes.NewBuffer(data), this.RawReq.Body))
|
||||
this.RawReq.Body = io.NopCloser(io.MultiReader(bytes.NewBuffer(data), this.RawReq.Body))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ func (this *HTTPRequest) doWebsocket(requestHost string) {
|
||||
// TODO 增加N次错误重试,重试的时候需要尝试不同的源站
|
||||
originConn, _, err := OriginConnect(this.origin, this.requestServerPort(), this.RawReq.RemoteAddr, requestHost)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusBadGateway, false)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to connect origin site", "源站连接失败", false)
|
||||
|
||||
// 增加失败次数
|
||||
SharedOriginStateManager.Fail(this.origin, requestHost, this.reverseProxy, func() {
|
||||
@@ -65,13 +65,13 @@ func (this *HTTPRequest) doWebsocket(requestHost string) {
|
||||
|
||||
err = this.RawReq.Write(originConn)
|
||||
if err != nil {
|
||||
this.write50x(err, http.StatusBadGateway, false)
|
||||
this.write50x(err, http.StatusBadGateway, "Failed to write request to origin site", "源站请求初始化失败", false)
|
||||
return
|
||||
}
|
||||
|
||||
clientConn, _, err := this.writer.Hijack()
|
||||
if err != nil || clientConn == nil {
|
||||
this.write50x(err, http.StatusInternalServerError, false)
|
||||
this.write50x(err, http.StatusInternalServerError, "Failed to get origin site connection", "获取源站连接失败", false)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
@@ -524,7 +523,7 @@ func (this *HTTPWriter) PrepareWebP(resp *http.Response, size int64) {
|
||||
|
||||
this.webpOriginContentType = contentType
|
||||
this.webpIsEncoding = true
|
||||
resp.Body = ioutil.NopCloser(&bytes.Buffer{})
|
||||
resp.Body = io.NopCloser(&bytes.Buffer{})
|
||||
this.delayRead = true
|
||||
|
||||
this.Header().Del("Content-Length")
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/stats"
|
||||
@@ -108,8 +109,9 @@ func (this *TCPListener) handleConn(conn net.Conn) error {
|
||||
// 记录域名排行
|
||||
tlsConn, ok := conn.(*tls.Conn)
|
||||
var recordStat = false
|
||||
var serverName = ""
|
||||
if ok {
|
||||
var serverName = tlsConn.ConnectionState().ServerName
|
||||
serverName = tlsConn.ConnectionState().ServerName
|
||||
if len(serverName) > 0 {
|
||||
// 统计
|
||||
stats.SharedTrafficStatManager.Add(server.Id, serverName, 0, 0, 1, 0, 0, 0, server.ShouldCheckTrafficLimit(), server.PlanId())
|
||||
@@ -122,8 +124,9 @@ func (this *TCPListener) handleConn(conn net.Conn) error {
|
||||
stats.SharedTrafficStatManager.Add(server.Id, "", 0, 0, 1, 0, 0, 0, server.ShouldCheckTrafficLimit(), server.PlanId())
|
||||
}
|
||||
|
||||
originConn, err := this.connectOrigin(server.Id, server.ReverseProxy, conn.RemoteAddr().String())
|
||||
originConn, err := this.connectOrigin(server.Id, serverName, server.ReverseProxy, conn.RemoteAddr().String())
|
||||
if err != nil {
|
||||
_ = conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -218,37 +221,63 @@ func (this *TCPListener) Close() error {
|
||||
}
|
||||
|
||||
// 连接源站
|
||||
func (this *TCPListener) connectOrigin(serverId int64, reverseProxy *serverconfigs.ReverseProxyConfig, remoteAddr string) (conn net.Conn, err error) {
|
||||
func (this *TCPListener) connectOrigin(serverId int64, requestHost string, reverseProxy *serverconfigs.ReverseProxyConfig, remoteAddr string) (conn net.Conn, err error) {
|
||||
if reverseProxy == nil {
|
||||
return nil, errors.New("no reverse proxy config")
|
||||
}
|
||||
|
||||
var requestCall = shared.NewRequestCall()
|
||||
requestCall.Domain = requestHost
|
||||
|
||||
var retries = 3
|
||||
var addr string
|
||||
|
||||
var failedOriginIds []int64
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
var origin = reverseProxy.NextOrigin(nil)
|
||||
var origin *serverconfigs.OriginConfig
|
||||
if len(failedOriginIds) > 0 {
|
||||
origin = reverseProxy.AnyOrigin(requestCall, failedOriginIds)
|
||||
}
|
||||
if origin == nil {
|
||||
origin = reverseProxy.NextOrigin(requestCall)
|
||||
}
|
||||
if origin == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// 回源主机名
|
||||
var requestHost = ""
|
||||
if len(reverseProxy.RequestHost) > 0 {
|
||||
requestHost = reverseProxy.RequestHost
|
||||
}
|
||||
if len(origin.RequestHost) > 0 {
|
||||
requestHost = origin.RequestHost
|
||||
} else if len(reverseProxy.RequestHost) > 0 {
|
||||
requestHost = reverseProxy.RequestHost
|
||||
}
|
||||
|
||||
conn, addr, err = OriginConnect(origin, this.port, remoteAddr, requestHost)
|
||||
if err != nil {
|
||||
failedOriginIds = append(failedOriginIds, origin.Id)
|
||||
|
||||
remotelogs.ServerError(serverId, "TCP_LISTENER", "unable to connect origin server: "+addr+": "+err.Error(), "", nil)
|
||||
|
||||
SharedOriginStateManager.Fail(origin, requestHost, reverseProxy, func() {
|
||||
reverseProxy.ResetScheduling()
|
||||
})
|
||||
|
||||
continue
|
||||
} else {
|
||||
if !origin.IsOk {
|
||||
SharedOriginStateManager.Success(origin, func() {
|
||||
reverseProxy.ResetScheduling()
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("server '" + types.String(serverId) + "': no available origin server can be used")
|
||||
|
||||
if err == nil {
|
||||
err = errors.New("server '" + types.String(serverId) + "': no available origin server can be used")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
UDPConnLifeSeconds = 30
|
||||
)
|
||||
|
||||
type UDPListener struct {
|
||||
BaseListener
|
||||
|
||||
@@ -135,16 +139,39 @@ func (this *UDPListener) connectOrigin(serverId int64, reverseProxy *serverconfi
|
||||
|
||||
var retries = 3
|
||||
var addr string
|
||||
|
||||
var failedOriginIds []int64
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
var origin = reverseProxy.NextOrigin(nil)
|
||||
var origin *serverconfigs.OriginConfig
|
||||
if len(failedOriginIds) > 0 {
|
||||
origin = reverseProxy.AnyOrigin(nil, failedOriginIds)
|
||||
}
|
||||
if origin == nil {
|
||||
origin = reverseProxy.NextOrigin(nil)
|
||||
}
|
||||
if origin == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
conn, addr, err = OriginConnect(origin, this.port, remoteAddr.String(), "")
|
||||
if err != nil {
|
||||
failedOriginIds = append(failedOriginIds, origin.Id)
|
||||
|
||||
remotelogs.ServerError(serverId, "UDP_LISTENER", "unable to connect origin server: "+addr+": "+err.Error(), "", nil)
|
||||
|
||||
SharedOriginStateManager.Fail(origin, "", reverseProxy, func() {
|
||||
reverseProxy.ResetScheduling()
|
||||
})
|
||||
|
||||
continue
|
||||
} else {
|
||||
if !origin.IsOk {
|
||||
SharedOriginStateManager.Success(origin, func() {
|
||||
reverseProxy.ResetScheduling()
|
||||
})
|
||||
}
|
||||
|
||||
// PROXY Protocol
|
||||
if reverseProxy != nil &&
|
||||
reverseProxy.ProxyProtocol != nil &&
|
||||
@@ -171,14 +198,17 @@ func (this *UDPListener) connectOrigin(serverId int64, reverseProxy *serverconfi
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("server '" + types.String(serverId) + "': no available origin server can be used")
|
||||
|
||||
if err == nil {
|
||||
err = errors.New("server '" + types.String(serverId) + "': no available origin server can be used")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 回收连接
|
||||
func (this *UDPListener) gcConns() {
|
||||
this.connLocker.Lock()
|
||||
closingConns := []*UDPConn{}
|
||||
var closingConns = []*UDPConn{}
|
||||
for addr, conn := range this.connMap {
|
||||
if !conn.IsOk() {
|
||||
closingConns = append(closingConns, conn)
|
||||
@@ -203,7 +233,7 @@ type UDPConn struct {
|
||||
}
|
||||
|
||||
func NewUDPConn(server *serverconfigs.ServerConfig, addr net.Addr, proxyConn *net.UDPConn, serverConn *net.UDPConn) *UDPConn {
|
||||
conn := &UDPConn{
|
||||
var conn = &UDPConn{
|
||||
addr: addr,
|
||||
proxyConn: proxyConn,
|
||||
serverConn: serverConn,
|
||||
@@ -217,7 +247,7 @@ func NewUDPConn(server *serverconfigs.ServerConfig, addr net.Addr, proxyConn *ne
|
||||
}
|
||||
|
||||
goman.New(func() {
|
||||
buffer := utils.BytePool4k.Get()
|
||||
var buffer = utils.BytePool4k.Get()
|
||||
defer func() {
|
||||
utils.BytePool4k.Put(buffer)
|
||||
}()
|
||||
@@ -232,9 +262,13 @@ func NewUDPConn(server *serverconfigs.ServerConfig, addr net.Addr, proxyConn *ne
|
||||
break
|
||||
}
|
||||
|
||||
// 记录流量
|
||||
// 记录流量和带宽
|
||||
if server != nil {
|
||||
// 流量
|
||||
stats.SharedTrafficStatManager.Add(server.Id, "", int64(n), 0, 0, 0, 0, 0, server.ShouldCheckTrafficLimit(), server.PlanId())
|
||||
|
||||
// 带宽
|
||||
stats.SharedBandwidthStatManager.Add(server.UserId, server.Id, int64(n))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@@ -268,5 +302,5 @@ func (this *UDPConn) IsOk() bool {
|
||||
if !this.isOk {
|
||||
return false
|
||||
}
|
||||
return time.Now().Unix()-this.activatedAt < 30 // 如果超过 N 秒没有活动我们认为是超时
|
||||
return time.Now().Unix()-this.activatedAt < UDPConnLifeSeconds // 如果超过 N 秒没有活动我们认为是超时
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -207,8 +206,9 @@ func (this *Node) Start() {
|
||||
|
||||
// Daemon 实现守护进程
|
||||
func (this *Node) Daemon() {
|
||||
isDebug := lists.ContainsString(os.Args, "debug")
|
||||
isDebug = true
|
||||
teaconst.IsDaemon = true
|
||||
|
||||
var isDebug = lists.ContainsString(os.Args, "debug")
|
||||
for {
|
||||
conn, err := this.sock.Dial()
|
||||
if err != nil {
|
||||
@@ -227,13 +227,18 @@ func (this *Node) Daemon() {
|
||||
_ = os.Setenv("EdgeDaemon", "on")
|
||||
_ = os.Setenv("EdgeBackground", "on")
|
||||
|
||||
cmd := exec.Command(exe)
|
||||
var cmd = exec.Command(exe)
|
||||
var buf = &bytes.Buffer{}
|
||||
cmd.Stderr = buf
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
if isDebug {
|
||||
log.Println("[DAEMON]" + buf.String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -291,12 +296,20 @@ func (this *Node) loop() error {
|
||||
var nodeCtx = rpcClient.Context()
|
||||
tasksResp, err := rpcClient.NodeTaskRPC().FindNodeTasks(nodeCtx, &pb.FindNodeTasksRequest{})
|
||||
if err != nil {
|
||||
if rpc.IsConnError(err) && !Tea.IsTesting() {
|
||||
return nil
|
||||
}
|
||||
return errors.New("read node tasks failed: " + err.Error())
|
||||
}
|
||||
for _, task := range tasksResp.NodeTasks {
|
||||
switch task.Type {
|
||||
case "ipItemChanged":
|
||||
iplibrary.IPListUpdateNotify <- true
|
||||
// 防止阻塞
|
||||
select {
|
||||
case iplibrary.IPListUpdateNotify <- true:
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
// 修改为已同步
|
||||
_, err = rpcClient.NodeTaskRPC().ReportNodeTaskDone(nodeCtx, &pb.ReportNodeTaskDoneRequest{
|
||||
@@ -333,11 +346,12 @@ func (this *Node) loop() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case "nodeVersionChanged":
|
||||
goman.New(func() {
|
||||
sharedUpgradeManager.Start()
|
||||
})
|
||||
if !sharedUpgradeManager.IsInstalling() {
|
||||
goman.New(func() {
|
||||
sharedUpgradeManager.Start()
|
||||
})
|
||||
}
|
||||
case "scriptsChanged":
|
||||
err = this.reloadCommonScripts()
|
||||
if err != nil {
|
||||
@@ -605,7 +619,7 @@ func (this *Node) startSyncTimer() {
|
||||
// 检查集群设置
|
||||
func (this *Node) checkClusterConfig() error {
|
||||
configFile := Tea.ConfigFile("cluster.yaml")
|
||||
data, err := ioutil.ReadFile(configFile)
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -675,7 +689,7 @@ func (this *Node) listenSock() error {
|
||||
if this.sock.IsListening() {
|
||||
reply, err := this.sock.Send(&gosock.Command{Code: "pid"})
|
||||
if err == nil {
|
||||
return errors.New("error: the process is already running, pid: " + maps.NewMap(reply.Params).GetString("pid"))
|
||||
return errors.New("error: the process is already running, pid: " + types.String(maps.NewMap(reply.Params).GetInt("pid")))
|
||||
} else {
|
||||
return errors.New("error: the process is already running")
|
||||
}
|
||||
@@ -713,6 +727,7 @@ func (this *Node) listenSock() error {
|
||||
_ = this.sock.Close()
|
||||
|
||||
events.Notify(events.EventQuit)
|
||||
events.Notify(events.EventTerminated)
|
||||
|
||||
// 监控连接数,如果连接数为0,则退出进程
|
||||
goman.New(func() {
|
||||
@@ -776,7 +791,8 @@ func (this *Node) listenSock() error {
|
||||
var m = maps.NewMap(cmd.Params)
|
||||
var ip = m.GetString("ip")
|
||||
var timeSeconds = m.GetInt("timeoutSeconds")
|
||||
err := firewalls.Firewall().DropSourceIP(ip, timeSeconds)
|
||||
var async = m.GetBool("async")
|
||||
err := firewalls.Firewall().DropSourceIP(ip, timeSeconds, async)
|
||||
if err != nil {
|
||||
_ = cmd.Reply(&gosock.Command{
|
||||
Params: map[string]interface{}{
|
||||
@@ -999,7 +1015,7 @@ func (this *Node) checkDisk() {
|
||||
"/sys/block/vda/queue/rotational",
|
||||
"/sys/block/sda/queue/rotational",
|
||||
} {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
@@ -25,7 +24,7 @@ func (this *Node) handlePanic() {
|
||||
var panicFile = Tea.Root + "/logs/panic.log"
|
||||
|
||||
// 分析panic
|
||||
data, err := ioutil.ReadFile(panicFile)
|
||||
data, err := os.ReadFile(panicFile)
|
||||
if err == nil {
|
||||
var index = bytes.Index(data, []byte("panic:"))
|
||||
if index >= 0 {
|
||||
|
||||
@@ -30,10 +30,14 @@ type NodeStatusExecutor struct {
|
||||
cpuUpdatedTime time.Time
|
||||
cpuLogicalCount int
|
||||
cpuPhysicalCount int
|
||||
|
||||
ticker *time.Ticker
|
||||
}
|
||||
|
||||
func NewNodeStatusExecutor() *NodeStatusExecutor {
|
||||
return &NodeStatusExecutor{}
|
||||
return &NodeStatusExecutor{
|
||||
ticker: time.NewTicker(30 * time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
func (this *NodeStatusExecutor) Listen() {
|
||||
@@ -41,15 +45,12 @@ func (this *NodeStatusExecutor) Listen() {
|
||||
this.cpuUpdatedTime = time.Now()
|
||||
this.update()
|
||||
|
||||
// TODO 这个时间间隔可以配置
|
||||
var ticker = time.NewTicker(30 * time.Second)
|
||||
|
||||
events.OnKey(events.EventQuit, this, func() {
|
||||
remotelogs.Println("NODE_STATUS", "quit executor")
|
||||
ticker.Stop()
|
||||
this.ticker.Stop()
|
||||
})
|
||||
|
||||
for range ticker.C {
|
||||
for range this.ticker.C {
|
||||
this.isFirstTime = false
|
||||
this.update()
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
@@ -104,7 +103,7 @@ func (this *SystemServiceManager) setupSystemd(params maps.Map) error {
|
||||
|
||||
if output == "enabled" {
|
||||
// 检查文件路径是否变化
|
||||
data, err := ioutil.ReadFile("/etc/systemd/system/" + teaconst.SystemdServiceName + ".service")
|
||||
data, err := os.ReadFile("/etc/systemd/system/" + teaconst.SystemdServiceName + ".service")
|
||||
if err == nil && bytes.Index(data, []byte(exe)) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||
"github.com/iwind/gosock/pkg/gosock"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
@@ -46,15 +48,12 @@ func (this *UpgradeManager) Start() {
|
||||
}
|
||||
this.isInstalling = true
|
||||
|
||||
// 还原安装状态
|
||||
defer func() {
|
||||
this.isInstalling = false
|
||||
}()
|
||||
|
||||
remotelogs.Println("UPGRADE_MANAGER", "upgrading node ...")
|
||||
err := this.install()
|
||||
if err != nil {
|
||||
remotelogs.Error("UPGRADE_MANAGER", "download failed: "+err.Error())
|
||||
|
||||
this.isInstalling = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -65,9 +64,16 @@ func (this *UpgradeManager) Start() {
|
||||
if err != nil {
|
||||
remotelogs.Error("UPGRADE_MANAGER", err.Error())
|
||||
}
|
||||
|
||||
this.isInstalling = false
|
||||
})
|
||||
}
|
||||
|
||||
// IsInstalling 检查是否正在安装
|
||||
func (this *UpgradeManager) IsInstalling() bool {
|
||||
return this.isInstalling
|
||||
}
|
||||
|
||||
func (this *UpgradeManager) install() error {
|
||||
// 检查是否有已下载但未安装成功的
|
||||
if len(this.lastFile) > 0 {
|
||||
@@ -83,7 +89,7 @@ func (this *UpgradeManager) install() error {
|
||||
}
|
||||
|
||||
// 创建临时文件
|
||||
dir := Tea.Root + "/tmp"
|
||||
var dir = Tea.Root + "/tmp"
|
||||
_, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -98,7 +104,7 @@ func (this *UpgradeManager) install() error {
|
||||
|
||||
remotelogs.Println("UPGRADE_MANAGER", "downloading new node ...")
|
||||
|
||||
path := dir + "/edge-node" + ".tmp"
|
||||
var path = dir + "/edge-node" + ".tmp"
|
||||
fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -203,16 +209,16 @@ func (this *UpgradeManager) unzip(zipPath string) error {
|
||||
}
|
||||
|
||||
// 先改先前的可执行文件
|
||||
err := os.Rename(target+"/bin/edge-node", target+"/bin/.edge-node.dist")
|
||||
hasBackup := err == nil
|
||||
err := os.Rename(target+"/bin/"+teaconst.ProcessName, target+"/bin/."+teaconst.ProcessName+".dist")
|
||||
var hasBackup = err == nil
|
||||
defer func() {
|
||||
if !isOk && hasBackup {
|
||||
// 失败时还原
|
||||
_ = os.Rename(target+"/bin/.edge-node.dist", target+"/bin/edge-node")
|
||||
_ = os.Rename(target+"/bin/."+teaconst.ProcessName+".dist", target+"/bin/"+teaconst.ProcessName)
|
||||
}
|
||||
}()
|
||||
|
||||
unzip := utils.NewUnzip(zipPath, target, "edge-node/")
|
||||
var unzip = utils.NewUnzip(zipPath, target, "edge-node/")
|
||||
err = unzip.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -225,6 +231,9 @@ func (this *UpgradeManager) unzip(zipPath string) error {
|
||||
|
||||
// 重启
|
||||
func (this *UpgradeManager) restart() error {
|
||||
// 关闭当前sock,防止无法重启
|
||||
_ = gosock.NewTmpSock(teaconst.ProcessName).Close()
|
||||
|
||||
// 重新启动
|
||||
if DaemonIsOn && DaemonPid == os.Getppid() {
|
||||
utils.Exit() // TODO 试着更优雅重启
|
||||
@@ -241,7 +250,9 @@ func (this *UpgradeManager) restart() error {
|
||||
events.Notify(events.EventTerminated)
|
||||
|
||||
// 启动
|
||||
cmd := exec.Command(exe, "start")
|
||||
exe = filepath.Dir(exe) + "/" + teaconst.ProcessName
|
||||
|
||||
var cmd = exec.Command(exe, "start")
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -109,6 +109,8 @@ func TestRegexp_ParseKeywords3(t *testing.T) {
|
||||
|
||||
func BenchmarkRegexp_MatchString(b *testing.B) {
|
||||
var r = re.MustCompile("(?i)(onmouseover|onmousemove|onmousedown|onmouseup|onerror|onload|onclick|ondblclick|onkeydown|onkeyup|onkeypress)(\\s|%09|%0A|(\\+|%20))*(=|%3D)")
|
||||
b.ResetTimer()
|
||||
|
||||
//b.Log("keywords:", r.Keywords())
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.MatchString("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
|
||||
@@ -117,6 +119,8 @@ func BenchmarkRegexp_MatchString(b *testing.B) {
|
||||
|
||||
func BenchmarkRegexp_MatchString2(b *testing.B) {
|
||||
var r = regexp.MustCompile("(?i)(onmouseover|onmousemove|onmousedown|onmouseup|onerror|onload|onclick|ondblclick|onkeydown|onkeyup|onkeypress)(\\s|%09|%0A|(\\+|%20))*(=|%3D)")
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.MatchString("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func (this *TrafficStatManager) Add(serverId int64, domain string, bytes int64,
|
||||
this.totalRequests++
|
||||
|
||||
var timestamp = utils.FloorUnixTime(300)
|
||||
key := strconv.FormatInt(timestamp, 10) + strconv.FormatInt(serverId, 10)
|
||||
var key = strconv.FormatInt(timestamp, 10) + strconv.FormatInt(serverId, 10)
|
||||
this.locker.Lock()
|
||||
|
||||
// 总的流量
|
||||
|
||||
@@ -1,108 +1,46 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"time"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var BytePool1k = NewBytePool(20480, 1024)
|
||||
var BytePool4k = NewBytePool(20480, 4*1024)
|
||||
var BytePool16k = NewBytePool(40960, 16*1024)
|
||||
var BytePool32k = NewBytePool(20480, 32*1024)
|
||||
var BytePool1k = NewBytePool(1024)
|
||||
var BytePool4k = NewBytePool(4 * 1024)
|
||||
var BytePool16k = NewBytePool(16 * 1024)
|
||||
var BytePool32k = NewBytePool(32 * 1024)
|
||||
|
||||
// BytePool pool for get byte slice
|
||||
type BytePool struct {
|
||||
c chan []byte
|
||||
maxSize int
|
||||
length int
|
||||
hasNew bool
|
||||
rawPool *sync.Pool
|
||||
}
|
||||
|
||||
// NewBytePool 创建新对象
|
||||
func NewBytePool(maxSize, length int) *BytePool {
|
||||
if maxSize <= 0 {
|
||||
maxSize = 1024
|
||||
func NewBytePool(length int) *BytePool {
|
||||
if length < 0 {
|
||||
length = 1024
|
||||
}
|
||||
if length <= 0 {
|
||||
length = 128
|
||||
return &BytePool{
|
||||
length: length,
|
||||
rawPool: &sync.Pool{
|
||||
New: func() any {
|
||||
return make([]byte, length)
|
||||
},
|
||||
},
|
||||
}
|
||||
var pool = &BytePool{
|
||||
c: make(chan []byte, maxSize),
|
||||
maxSize: maxSize,
|
||||
length: length,
|
||||
}
|
||||
|
||||
pool.init()
|
||||
|
||||
return pool
|
||||
}
|
||||
|
||||
// 初始化
|
||||
func (this *BytePool) init() {
|
||||
var ticker = time.NewTicker(2 * time.Minute)
|
||||
if Tea.IsTesting() {
|
||||
ticker = time.NewTicker(5 * time.Second)
|
||||
}
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
if this.hasNew {
|
||||
this.hasNew = false
|
||||
continue
|
||||
}
|
||||
|
||||
this.Purge()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Get 获取一个新的byte slice
|
||||
func (this *BytePool) Get() (b []byte) {
|
||||
select {
|
||||
case b = <-this.c:
|
||||
default:
|
||||
b = make([]byte, this.length)
|
||||
this.hasNew = true
|
||||
}
|
||||
return
|
||||
func (this *BytePool) Get() []byte {
|
||||
return this.rawPool.Get().([]byte)
|
||||
}
|
||||
|
||||
// Put 放回一个使用过的byte slice
|
||||
func (this *BytePool) Put(b []byte) {
|
||||
if cap(b) != this.length {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case this.c <- b:
|
||||
default:
|
||||
// 已达最大容量,则抛弃
|
||||
}
|
||||
this.rawPool.Put(b)
|
||||
}
|
||||
|
||||
// Length 单个字节slice长度
|
||||
func (this *BytePool) Length() int {
|
||||
return this.length
|
||||
}
|
||||
|
||||
// Size 当前的数量
|
||||
func (this *BytePool) Size() int {
|
||||
return len(this.c)
|
||||
}
|
||||
|
||||
// Purge 清理
|
||||
func (this *BytePool) Purge() {
|
||||
// 1%
|
||||
var count = len(this.c) / 100
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
Loop:
|
||||
for i := 0; i < count; i++ {
|
||||
select {
|
||||
case <-this.c:
|
||||
default:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,16 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/assert"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBytePool(t *testing.T) {
|
||||
a := assert.NewAssertion(t)
|
||||
|
||||
pool := NewBytePool(5, 8)
|
||||
buf := pool.Get()
|
||||
a.IsTrue(len(buf) == 8)
|
||||
a.IsTrue(len(pool.c) == 0)
|
||||
|
||||
pool.Put(buf)
|
||||
a.IsTrue(len(pool.c) == 1)
|
||||
|
||||
pool.Get()
|
||||
a.IsTrue(len(pool.c) == 0)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
pool.Put(buf)
|
||||
}
|
||||
t.Log(len(pool.c))
|
||||
a.IsTrue(len(pool.c) == 5)
|
||||
}
|
||||
|
||||
func TestBytePool_Memory(t *testing.T) {
|
||||
var stat1 = &runtime.MemStats{}
|
||||
runtime.ReadMemStats(stat1)
|
||||
|
||||
var pool = NewBytePool(20480, 32*1024)
|
||||
var pool = NewBytePool(32 * 1024)
|
||||
for i := 0; i < 20480; i++ {
|
||||
pool.Put(make([]byte, 32*1024))
|
||||
}
|
||||
@@ -44,18 +23,50 @@ func TestBytePool_Memory(t *testing.T) {
|
||||
|
||||
var stat2 = &runtime.MemStats{}
|
||||
runtime.ReadMemStats(stat2)
|
||||
t.Log((stat2.HeapInuse-stat1.HeapInuse)/1024/1024, "MB,", pool.Size(), "slices")
|
||||
t.Log((stat2.HeapInuse-stat1.HeapInuse)/1024/1024, "MB,")
|
||||
}
|
||||
|
||||
func BenchmarkBytePool_Get(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
pool := NewBytePool(1024, 1)
|
||||
var pool = NewBytePool(1)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf := pool.Get()
|
||||
var buf = pool.Get()
|
||||
_ = buf
|
||||
pool.Put(buf)
|
||||
}
|
||||
|
||||
b.Log(pool.Size())
|
||||
}
|
||||
|
||||
func BenchmarkBytePool_Get_Parallel(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
var pool = NewBytePool(1024)
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
var buf = pool.Get()
|
||||
pool.Put(buf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkBytePool_Get_Sync(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
var pool = &sync.Pool{
|
||||
New: func() any {
|
||||
return make([]byte, 1024)
|
||||
},
|
||||
}
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
var buf = pool.Get()
|
||||
pool.Put(buf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package utils
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"sync"
|
||||
@@ -19,7 +19,7 @@ func DumpResponse(resp *http.Response) (header []byte, body []byte, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
body, err = ioutil.ReadAll(resp.Body)
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"net"
|
||||
"sort"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@@ -26,47 +25,3 @@ func ListenReuseAddr(network string, addr string) (net.Listener, error) {
|
||||
}
|
||||
return config.Listen(context.Background(), network, addr)
|
||||
}
|
||||
|
||||
// ParseAddrHost 分析地址中的主机名部分
|
||||
func ParseAddrHost(addr string) string {
|
||||
if len(addr) == 0 {
|
||||
return addr
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return addr
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
// MergePorts 聚合端口
|
||||
// 返回 [ [fromPort, toPort], ... ]
|
||||
func MergePorts(ports []int) [][2]int {
|
||||
if len(ports) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sort.Ints(ports)
|
||||
|
||||
var result = [][2]int{}
|
||||
var lastRange = [2]int{0, 0}
|
||||
var lastPort = -1
|
||||
for _, port := range ports {
|
||||
if port <= 0 /** 只处理有效的端口 **/ || port == lastPort /** 去重 **/ {
|
||||
continue
|
||||
}
|
||||
|
||||
if lastPort < 0 || port != lastPort+1 {
|
||||
lastRange = [2]int{port, port}
|
||||
result = append(result, lastRange)
|
||||
} else { // 如果是连续的
|
||||
lastRange[1] = port
|
||||
result[len(result)-1] = lastRange
|
||||
}
|
||||
|
||||
lastPort = port
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
52
internal/utils/net_utils.go
Normal file
52
internal/utils/net_utils.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// ParseAddrHost 分析地址中的主机名部分
|
||||
func ParseAddrHost(addr string) string {
|
||||
if len(addr) == 0 {
|
||||
return addr
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return addr
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
// MergePorts 聚合端口
|
||||
// 返回 [ [fromPort, toPort], ... ]
|
||||
func MergePorts(ports []int) [][2]int {
|
||||
if len(ports) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sort.Ints(ports)
|
||||
|
||||
var result = [][2]int{}
|
||||
var lastRange = [2]int{0, 0}
|
||||
var lastPort = -1
|
||||
for _, port := range ports {
|
||||
if port <= 0 /** 只处理有效的端口 **/ || port == lastPort /** 去重 **/ {
|
||||
continue
|
||||
}
|
||||
|
||||
if lastPort < 0 || port != lastPort+1 {
|
||||
lastRange = [2]int{port, port}
|
||||
result = append(result, lastRange)
|
||||
} else { // 如果是连续的
|
||||
lastRange[1] = port
|
||||
result[len(result)-1] = lastRange
|
||||
}
|
||||
|
||||
lastPort = port
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils/readers"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/textproto"
|
||||
"testing"
|
||||
)
|
||||
@@ -17,7 +16,7 @@ func TestNewByteRangesReader(t *testing.T) {
|
||||
var dashBoundary = "--" + boundary
|
||||
var b = bytes.NewReader([]byte(dashBoundary + "\r\nContent-Range: bytes 0-4/36\r\nContent-Type: text/plain\r\n\r\n01234\r\n" + dashBoundary + "\r\nContent-Range: bytes 5-9/36\r\nContent-Type: text/plain\r\n\r\n56789\r\n--" + boundary + "\r\nContent-Range: bytes 10-12/36\r\nContent-Type: text/plain\r\n\r\nabc\r\n" + dashBoundary + "--\r\n"))
|
||||
|
||||
var reader = readers.NewByteRangesReaderCloser(ioutil.NopCloser(b), boundary)
|
||||
var reader = readers.NewByteRangesReaderCloser(io.NopCloser(b), boundary)
|
||||
var p = make([]byte, 16)
|
||||
for {
|
||||
n, err := reader.Read(p)
|
||||
@@ -38,7 +37,7 @@ func TestByteRangesReader_OnPartRead(t *testing.T) {
|
||||
var dashBoundary = "--" + boundary
|
||||
var b = bytes.NewReader([]byte(dashBoundary + "\r\nContent-Range: bytes 0-4/36\r\nContent-Type: text/plain\r\n\r\n01234\r\n" + dashBoundary + "\r\nContent-Range: bytes 5-9/36\r\nContent-Type: text/plain\r\n\r\n56789\r\n--" + boundary + "\r\nContent-Range: bytes 10-12/36\r\nContent-Type: text/plain\r\n\r\nabc\r\n" + dashBoundary + "--\r\n"))
|
||||
|
||||
var reader = readers.NewByteRangesReaderCloser(ioutil.NopCloser(b), boundary)
|
||||
var reader = readers.NewByteRangesReaderCloser(io.NopCloser(b), boundary)
|
||||
reader.OnPartRead(func(start int64, end int64, total int64, data []byte, header textproto.MIMEHeader) {
|
||||
t.Log(start, "-", end, "/", total, string(data))
|
||||
})
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
@@ -83,13 +82,13 @@ func (this *ServiceManager) installInitService(exePath string, args []string) er
|
||||
return errors.New("'scripts/" + shortName + "' file not exists")
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(scriptFile)
|
||||
data, err := os.ReadFile(scriptFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data = regexp.MustCompile("INSTALL_DIR=.+").ReplaceAll(data, []byte("INSTALL_DIR="+Tea.Root))
|
||||
err = ioutil.WriteFile(initServiceFile, data, 0777)
|
||||
err = os.WriteFile(initServiceFile, data, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -137,7 +136,7 @@ ExecReload=` + exePath + ` reload
|
||||
WantedBy=multi-user.target`
|
||||
|
||||
// write file
|
||||
err := ioutil.WriteFile(systemdServiceFile, []byte(desc), 0777)
|
||||
err := os.WriteFile(systemdServiceFile, []byte(desc), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,18 +2,21 @@ package utils
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
var unixTime = time.Now().Unix()
|
||||
var unixTimeMilli = time.Now().UnixMilli()
|
||||
var unixTimeMilliString = types.String(unixTimeMilli)
|
||||
|
||||
func init() {
|
||||
ticker := time.NewTicker(200 * time.Millisecond)
|
||||
var ticker = time.NewTicker(200 * time.Millisecond)
|
||||
goman.New(func() {
|
||||
for range ticker.C {
|
||||
unixTime = time.Now().Unix()
|
||||
unixTimeMilli = time.Now().UnixMilli()
|
||||
unixTimeMilliString = types.String(unixTimeMilli)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -43,6 +46,10 @@ func UnixTimeMilli() int64 {
|
||||
return unixTimeMilli
|
||||
}
|
||||
|
||||
func UnixTimeMilliString() (int64, string) {
|
||||
return unixTimeMilli, unixTimeMilliString
|
||||
}
|
||||
|
||||
// GMTUnixTime 计算GMT时间戳
|
||||
func GMTUnixTime(timestamp int64) int64 {
|
||||
_, offset := time.Now().Zone()
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -111,7 +110,7 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque
|
||||
path = Tea.Root + string(os.PathSeparator) + path
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return false
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -28,7 +28,7 @@ func TestRequestAllCheckpoint_RequestValue(t *testing.T) {
|
||||
t.Log(v)
|
||||
t.Log(types.String(v))
|
||||
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func TestRequestAllCheckpoint_RequestValue_Max(t *testing.T) {
|
||||
}
|
||||
t.Log("value bytes:", len(types.String(value)))
|
||||
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -19,7 +19,7 @@ func TestRequestBodyCheckpoint_RequestValue(t *testing.T) {
|
||||
checkpoint := new(RequestBodyCheckpoint)
|
||||
t.Log(checkpoint.RequestValue(req, "", nil, 1))
|
||||
|
||||
body, err := ioutil.ReadAll(rawReq.Body)
|
||||
body, err := io.ReadAll(rawReq.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func TestRequestBodyCheckpoint_RequestValue_Max(t *testing.T) {
|
||||
}
|
||||
t.Log("value bytes:", len(types.String(value)))
|
||||
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package checkpoints
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
@@ -24,7 +24,7 @@ func TestRequestFormArgCheckpoint_RequestValue(t *testing.T) {
|
||||
t.Log(checkpoint.RequestValue(req, "Hello", nil, 1))
|
||||
t.Log(checkpoint.RequestValue(req, "encoded", nil, 1))
|
||||
|
||||
body, err := ioutil.ReadAll(req.WAFRaw().Body)
|
||||
body, err := io.ReadAll(req.WAFRaw().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package checkpoints
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ func TestRequestJSONArgCheckpoint_RequestValue_Map(t *testing.T) {
|
||||
t.Log(checkpoint.RequestValue(req, "books", nil, 1))
|
||||
t.Log(checkpoint.RequestValue(req, "books.1", nil, 1))
|
||||
|
||||
body, err := ioutil.ReadAll(req.WAFRaw().Body)
|
||||
body, err := io.ReadAll(req.WAFRaw().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func TestRequestJSONArgCheckpoint_RequestValue_Array(t *testing.T) {
|
||||
t.Log(checkpoint.RequestValue(req, "0.books", nil, 1))
|
||||
t.Log(checkpoint.RequestValue(req, "0.books.1", nil, 1))
|
||||
|
||||
body, err := ioutil.ReadAll(req.WAFRaw().Body)
|
||||
body, err := io.ReadAll(req.WAFRaw().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func TestRequestJSONArgCheckpoint_RequestValue_Error(t *testing.T) {
|
||||
t.Log(checkpoint.RequestValue(req, "0.books", nil, 1))
|
||||
t.Log(checkpoint.RequestValue(req, "0.books.1", nil, 1))
|
||||
|
||||
body, err := ioutil.ReadAll(req.WAFRaw().Body)
|
||||
body, err := io.ReadAll(req.WAFRaw().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/utils"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -51,7 +51,7 @@ func (this *RequestUploadCheckpoint) RequestValue(req requests.Request, param st
|
||||
defer req.WAFRestoreBody(data)
|
||||
}
|
||||
oldBody := req.WAFRaw().Body
|
||||
req.WAFRaw().Body = ioutil.NopCloser(bytes.NewBuffer(bodyData))
|
||||
req.WAFRaw().Body = io.NopCloser(bytes.NewBuffer(bodyData))
|
||||
|
||||
err := req.WAFRaw().ParseMultipartForm(utils.MaxBodySize)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package checkpoints
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -94,7 +94,7 @@ func TestRequestUploadCheckpoint_RequestValue(t *testing.T) {
|
||||
t.Log(checkpoint.RequestValue(req, "name", nil, 1))
|
||||
t.Log(checkpoint.RequestValue(req, "ext", nil, 1))
|
||||
|
||||
data, err := ioutil.ReadAll(req.WAFRaw().Body)
|
||||
data, err := io.ReadAll(req.WAFRaw().Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ResponseBodyCheckpoint ${responseBody}
|
||||
@@ -33,7 +33,7 @@ func (this *ResponseBodyCheckpoint) ResponseValue(req requests.Request, resp *re
|
||||
value = string(resp.BodyData)
|
||||
return
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
sysErr = err
|
||||
return
|
||||
@@ -41,7 +41,7 @@ func (this *ResponseBodyCheckpoint) ResponseValue(req requests.Request, resp *re
|
||||
resp.BodyData = body
|
||||
_ = resp.Body.Close()
|
||||
value = body
|
||||
resp.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
resp.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package checkpoints
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
@@ -13,7 +13,7 @@ func TestResponseBodyCheckpoint_ResponseValue(t *testing.T) {
|
||||
resp.StatusCode = 200
|
||||
resp.Header = http.Header{}
|
||||
resp.Header.Set("Hello", "World")
|
||||
resp.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("Hello, World")))
|
||||
resp.Body = io.NopCloser(bytes.NewBuffer([]byte("Hello, World")))
|
||||
|
||||
checkpoint := new(ResponseBodyCheckpoint)
|
||||
t.Log(checkpoint.ResponseValue(nil, resp, "", nil, 1))
|
||||
@@ -21,7 +21,7 @@ func TestResponseBodyCheckpoint_ResponseValue(t *testing.T) {
|
||||
t.Log(checkpoint.ResponseValue(nil, resp, "", nil, 1))
|
||||
t.Log(checkpoint.ResponseValue(nil, resp, "", nil, 1))
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func (this *IPList) RecordIP(ipType string,
|
||||
if seconds > 3600 {
|
||||
seconds = 3600
|
||||
}
|
||||
_ = firewalls.Firewall().DropSourceIP(ip, int(seconds))
|
||||
_ = firewalls.Firewall().DropSourceIP(ip, int(seconds), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package requests
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
@@ -48,7 +47,7 @@ func (this *TestRequest) WAFRemoteIP() string {
|
||||
|
||||
func (this *TestRequest) WAFReadBody(max int64) (data []byte, err error) {
|
||||
if this.req.ContentLength > 0 {
|
||||
data, err = ioutil.ReadAll(io.LimitReader(this.req.Body, max))
|
||||
data, err = io.ReadAll(io.LimitReader(this.req.Body, max))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -58,7 +57,7 @@ func (this *TestRequest) WAFRestoreBody(data []byte) {
|
||||
rawReader := bytes.NewBuffer(data)
|
||||
buf := make([]byte, 1024)
|
||||
_, _ = io.CopyBuffer(rawReader, this.req.Body, buf)
|
||||
this.req.Body = ioutil.NopCloser(rawReader)
|
||||
this.req.Body = io.NopCloser(rawReader)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"github.com/iwind/TeaGo/files"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@@ -315,7 +315,7 @@ func (this *WAF) Save(path string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(path, data, 0644)
|
||||
return os.WriteFile(path, data, 0644)
|
||||
}
|
||||
|
||||
func (this *WAF) ContainsGroupCode(code string) bool {
|
||||
|
||||
Reference in New Issue
Block a user