Просмотр исходного кода

Merge branch 'master' into stable

tags/v2.1.10^2
9seconds 2 месяцев назад
Родитель
Сommit
f4b296d1e0
41 измененных файлов: 213 добавлений и 144 удалений
  1. 4
    4
      .mise.toml
  2. 27
    2
      README.md
  3. 2
    2
      events/event_stream.go
  4. 27
    54
      events/multi_observer.go
  5. 9
    0
      example.config.toml
  6. 1
    0
      go.mod
  7. 2
    0
      go.sum
  8. 4
    10
      internal/cli/access.go
  9. 10
    0
      internal/cli/run_proxy.go
  10. 1
    0
      internal/config/config.go
  11. 1
    0
      internal/config/parse.go
  12. 2
    2
      internal/config/type_bool_test.go
  13. 20
    0
      internal/proxyprotocol/adapter.go
  14. 25
    0
      internal/proxyprotocol/conn.go
  15. 4
    7
      ipblocklist/firehol.go
  16. 1
    1
      logger/init.go
  17. 1
    1
      logger/noop.go
  18. 1
    1
      logger/zerolog.go
  19. 23
    1
      mise.lock
  20. 1
    1
      mtglib/init.go
  21. 11
    11
      mtglib/init_internal_test.go
  22. 1
    1
      mtglib/internal/faketls/client_hello.go
  23. 2
    2
      mtglib/internal/faketls/conn.go
  24. 2
    2
      mtglib/internal/faketls/conn_test.go
  25. 1
    1
      mtglib/internal/faketls/pools.go
  26. 1
    1
      mtglib/internal/faketls/record/pools.go
  27. 2
    2
      mtglib/internal/faketls/welcome.go
  28. 1
    1
      mtglib/internal/faketls/welcome_test.go
  29. 1
    1
      mtglib/internal/obfuscated2/handshake_frame.go
  30. 1
    1
      mtglib/internal/obfuscated2/init_test.go
  31. 2
    2
      mtglib/internal/obfuscated2/pools.go
  32. 1
    1
      mtglib/internal/relay/init.go
  33. 1
    1
      mtglib/internal/relay/init_test.go
  34. 1
    1
      mtglib/internal/relay/pools.go
  35. 1
    1
      mtglib/proxy.go
  36. 1
    1
      mtglib/stream_context.go
  37. 8
    11
      network/circuit_breaker_internal_test.go
  38. 2
    2
      network/load_balanced_socks5.go
  39. 1
    1
      network/load_balanced_socks5_test.go
  40. 5
    13
      network/network.go
  41. 1
    1
      stats/pools.go

+ 4
- 4
.mise.toml Просмотреть файл

1
 [tools]
1
 [tools]
2
-go = "latest"
2
+"go:golang.org/x/pkgsite/cmd/pkgsite" = "latest"
3
 "go:golang.org/x/tools/gopls" = "latest"
3
 "go:golang.org/x/tools/gopls" = "latest"
4
 "go:mvdan.cc/gofumpt" = "latest"
4
 "go:mvdan.cc/gofumpt" = "latest"
5
+go = "latest"
6
+golangci-lint = "latest"
7
+goreleaser = "latest"
5
 
8
 
6
 [vars]
9
 [vars]
7
 fuzzflags = "-fuzztime=120s"
10
 fuzzflags = "-fuzztime=120s"
21
 
24
 
22
 [tasks.lint]
25
 [tasks.lint]
23
 description = "Run linter"
26
 description = "Run linter"
24
-tools.golangci-lint = "latest"
25
 run = "golangci-lint run"
27
 run = "golangci-lint run"
26
 
28
 
27
 [tasks.test]
29
 [tasks.test]
77
 
79
 
78
 [tasks.release]
80
 [tasks.release]
79
 description = "Create release tarballs"
81
 description = "Create release tarballs"
80
-tools.goreleaser = "latest"
81
 sources = ["**/*.go", "go.mod", "go.sum", ".goreleaser.yml"]
82
 sources = ["**/*.go", "go.mod", "go.sum", ".goreleaser.yml"]
82
 run = [
83
 run = [
83
     "goreleaser --snapshot --clean",
84
     "goreleaser --snapshot --clean",
92
 
93
 
93
 [tasks.docs]
94
 [tasks.docs]
94
 description = "Run doc server"
95
 description = "Run doc server"
95
-tools."go:golang.org/x/pkgsite/cmd/pkgsite" = "latest"
96
 run = "pkgsite -http 0.0.0.0:10000"
96
 run = "pkgsite -http 0.0.0.0:10000"
97
 
97
 
98
 [tasks.fmt]
98
 [tasks.fmt]

+ 27
- 2
README.md Просмотреть файл

10
 **If you use v1.0 or upgrade broke you proxy, please read the chapter
10
 **If you use v1.0 or upgrade broke you proxy, please read the chapter
11
 [Version 2](#version-2)**
11
 [Version 2](#version-2)**
12
 
12
 
13
+If you want to have a proxy that _supports adtag_ (possibility to promote a
14
+channel with a special Telegram bot), I recommend to use
15
+[telemt](https://github.com/telemt/telemt) project. v1 of mtg supports it
16
+but I do not see any reasonable point of using it: adtag requires communication
17
+via a fragile set of middle proxies, requires complex setup that must expose
18
+a public IPs, has lower bandwidth and latency.
19
+
20
+mtg idea is simple: minimal unbloated proxy that can handle a reasonable scale
21
+~10-20k simultaneous connections, has no user management, but ticks all
22
+checkboxes related to its main intent: provide a way to use Telegram.
23
+
13
 ## Rationale
24
 ## Rationale
14
 
25
 
15
 There are several available proxies for Telegram MTPROTO available. Here
26
 There are several available proxies for Telegram MTPROTO available. Here
18
 * [Official](https://github.com/TelegramMessenger/MTProxy)
29
 * [Official](https://github.com/TelegramMessenger/MTProxy)
19
 * [Python](https://github.com/alexbers/mtprotoproxy)
30
 * [Python](https://github.com/alexbers/mtprotoproxy)
20
 * [Erlang](https://github.com/seriyps/mtproto_proxy)
31
 * [Erlang](https://github.com/seriyps/mtproto_proxy)
32
+* [Telemt (Rust)](https://github.com/telemt/telemt)
21
 
33
 
22
 You can use any of these. They work great and all implementations have
34
 You can use any of these. They work great and all implementations have
23
 feature parity now. This includes support of adtag, replay attack
35
 feature parity now. This includes support of adtag, replay attack
40
   way of doing business I suppose. I think the only viable way is to
52
   way of doing business I suppose. I think the only viable way is to
41
   have a proxy that can be restored anywhere easily.
53
   have a proxy that can be restored anywhere easily.
42
 
54
 
55
+* **Supports proxy protocol v1/v2**
56
+
57
+  This makes integration with loadbalancers like HAProxy and ELB a first class
58
+  citizen by supporting their
59
+  [commuication protocols](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt).
60
+
43
 * **A single secret**
61
 * **A single secret**
44
 
62
 
45
   I think that multiple secrets solve no problems and just complex
63
   I think that multiple secrets solve no problems and just complex
162
 
180
 
163
 ## Getting started
181
 ## Getting started
164
 
182
 
183
+### Download mise
184
+
185
+mtg uses [mise](https://mise.jdx.dev/) to maintain its development
186
+dependencies + replaces a make for building things. Please
187
+[install](https://mise.jdx.dev/getting-started.html) it first.
188
+
165
 ### Download a tool
189
 ### Download a tool
166
 
190
 
167
 #### Download binaries
191
 #### Download binaries
198
 ```console
222
 ```console
199
 git clone https://github.com/9seconds/mtg.git
223
 git clone https://github.com/9seconds/mtg.git
200
 cd mtg
224
 cd mtg
201
-make static
225
+mise install
226
+mise tasks run build
202
 ```
227
 ```
203
 
228
 
204
 or for the docker image:
229
 or for the docker image:
205
 
230
 
206
 ```console
231
 ```console
207
-make docker
232
+mise tasks run image
208
 ```
233
 ```
209
 
234
 
210
 ### Generate secret
235
 ### Generate secret

+ 2
- 2
events/event_stream.go Просмотреть файл

2
 
2
 
3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
-	"math/rand"
5
+	"math/rand/v2"
6
 	"runtime"
6
 	"runtime"
7
 
7
 
8
 	"github.com/9seconds/mtg/v2/mtglib"
8
 	"github.com/9seconds/mtg/v2/mtglib"
64
 		chans:     make([]chan mtglib.Event, runtime.NumCPU()),
64
 		chans:     make([]chan mtglib.Event, runtime.NumCPU()),
65
 	}
65
 	}
66
 
66
 
67
-	for i := 0; i < runtime.NumCPU(); i++ {
67
+	for i := range runtime.NumCPU() {
68
 		rv.chans[i] = make(chan mtglib.Event, 1)
68
 		rv.chans[i] = make(chan mtglib.Event, 1)
69
 
69
 
70
 		if len(observerFactories) == 1 {
70
 		if len(observerFactories) == 1 {

+ 27
- 54
events/multi_observer.go Просмотреть файл

12
 
12
 
13
 func (m multiObserver) EventStart(evt mtglib.EventStart) {
13
 func (m multiObserver) EventStart(evt mtglib.EventStart) {
14
 	wg := &sync.WaitGroup{}
14
 	wg := &sync.WaitGroup{}
15
-	wg.Add(len(m.observers))
16
 
15
 
17
 	for _, v := range m.observers {
16
 	for _, v := range m.observers {
18
-		go func(obs Observer) {
19
-			defer wg.Done()
20
-
21
-			obs.EventStart(evt)
22
-		}(v)
17
+		wg.Go(func() {
18
+			v.EventStart(evt)
19
+		})
23
 	}
20
 	}
24
 
21
 
25
 	wg.Wait()
22
 	wg.Wait()
27
 
24
 
28
 func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
25
 func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
29
 	wg := &sync.WaitGroup{}
26
 	wg := &sync.WaitGroup{}
30
-	wg.Add(len(m.observers))
31
 
27
 
32
 	for _, v := range m.observers {
28
 	for _, v := range m.observers {
33
-		go func(obs Observer) {
34
-			defer wg.Done()
35
-
36
-			obs.EventConnectedToDC(evt)
37
-		}(v)
29
+		wg.Go(func() {
30
+			v.EventConnectedToDC(evt)
31
+		})
38
 	}
32
 	}
39
 
33
 
40
 	wg.Wait()
34
 	wg.Wait()
42
 
36
 
43
 func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
37
 func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
44
 	wg := &sync.WaitGroup{}
38
 	wg := &sync.WaitGroup{}
45
-	wg.Add(len(m.observers))
46
 
39
 
47
 	for _, v := range m.observers {
40
 	for _, v := range m.observers {
48
-		go func(obs Observer) {
49
-			defer wg.Done()
50
-
51
-			obs.EventDomainFronting(evt)
52
-		}(v)
41
+		wg.Go(func() {
42
+			v.EventDomainFronting(evt)
43
+		})
53
 	}
44
 	}
54
 
45
 
55
 	wg.Wait()
46
 	wg.Wait()
57
 
48
 
58
 func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
49
 func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
59
 	wg := &sync.WaitGroup{}
50
 	wg := &sync.WaitGroup{}
60
-	wg.Add(len(m.observers))
61
 
51
 
62
 	for _, v := range m.observers {
52
 	for _, v := range m.observers {
63
-		go func(obs Observer) {
64
-			defer wg.Done()
65
-
66
-			obs.EventTraffic(evt)
67
-		}(v)
53
+		wg.Go(func() {
54
+			v.EventTraffic(evt)
55
+		})
68
 	}
56
 	}
69
 
57
 
70
 	wg.Wait()
58
 	wg.Wait()
72
 
60
 
73
 func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
61
 func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
74
 	wg := &sync.WaitGroup{}
62
 	wg := &sync.WaitGroup{}
75
-	wg.Add(len(m.observers))
76
 
63
 
77
 	for _, v := range m.observers {
64
 	for _, v := range m.observers {
78
-		go func(obs Observer) {
79
-			defer wg.Done()
80
-
81
-			obs.EventFinish(evt)
82
-		}(v)
65
+		wg.Go(func() {
66
+			v.EventFinish(evt)
67
+		})
83
 	}
68
 	}
84
 
69
 
85
 	wg.Wait()
70
 	wg.Wait()
87
 
72
 
88
 func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimited) {
73
 func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimited) {
89
 	wg := &sync.WaitGroup{}
74
 	wg := &sync.WaitGroup{}
90
-	wg.Add(len(m.observers))
91
 
75
 
92
 	for _, v := range m.observers {
76
 	for _, v := range m.observers {
93
-		go func(obs Observer) {
94
-			defer wg.Done()
95
-
96
-			obs.EventConcurrencyLimited(evt)
97
-		}(v)
77
+		wg.Go(func() {
78
+			v.EventConcurrencyLimited(evt)
79
+		})
98
 	}
80
 	}
99
 
81
 
100
 	wg.Wait()
82
 	wg.Wait()
102
 
84
 
103
 func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
85
 func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
104
 	wg := &sync.WaitGroup{}
86
 	wg := &sync.WaitGroup{}
105
-	wg.Add(len(m.observers))
106
 
87
 
107
 	for _, v := range m.observers {
88
 	for _, v := range m.observers {
108
-		go func(obs Observer) {
109
-			defer wg.Done()
110
-
111
-			obs.EventIPBlocklisted(evt)
112
-		}(v)
89
+		wg.Go(func() {
90
+			v.EventIPBlocklisted(evt)
91
+		})
113
 	}
92
 	}
114
 
93
 
115
 	wg.Wait()
94
 	wg.Wait()
117
 
96
 
118
 func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
97
 func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
119
 	wg := &sync.WaitGroup{}
98
 	wg := &sync.WaitGroup{}
120
-	wg.Add(len(m.observers))
121
 
99
 
122
 	for _, v := range m.observers {
100
 	for _, v := range m.observers {
123
-		go func(obs Observer) {
124
-			defer wg.Done()
125
-
126
-			obs.EventReplayAttack(evt)
127
-		}(v)
101
+		wg.Go(func() {
102
+			v.EventReplayAttack(evt)
103
+		})
128
 	}
104
 	}
129
 
105
 
130
 	wg.Wait()
106
 	wg.Wait()
132
 
108
 
133
 func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
109
 func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
134
 	wg := &sync.WaitGroup{}
110
 	wg := &sync.WaitGroup{}
135
-	wg.Add(len(m.observers))
136
 
111
 
137
 	for _, v := range m.observers {
112
 	for _, v := range m.observers {
138
-		go func(obs Observer) {
139
-			defer wg.Done()
140
-
141
-			obs.EventIPListSize(evt)
142
-		}(v)
113
+		wg.Go(func() {
114
+			v.EventIPListSize(evt)
115
+		})
143
 	}
116
 	}
144
 
117
 
145
 	wg.Wait()
118
 	wg.Wait()

+ 9
- 0
example.config.toml Просмотреть файл

23
 # Host:port pair to run proxy on.
23
 # Host:port pair to run proxy on.
24
 bind-to = "0.0.0.0:3128"
24
 bind-to = "0.0.0.0:3128"
25
 
25
 
26
+# This defines what types of traffic mtg listens to. If you are not sure,
27
+# then definitely keep it disable. Enable it only and only if incoming traffic
28
+# is coming from some sort of load-balancer like HAProxy or ELB.
29
+# https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt
30
+#
31
+# mtg uses a library that supports v1 and v2 versions of ProxyProtocol.
32
+# default value is false.
33
+# proxy-protocol-listener = false
34
+
26
 # Defines how many concurrent connections are allowed to this proxy.
35
 # Defines how many concurrent connections are allowed to this proxy.
27
 # All other incoming connections are going to be dropped.
36
 # All other incoming connections are going to be dropped.
28
 concurrency = 8192
37
 concurrency = 8192

+ 1
- 0
go.mod Просмотреть файл

28
 
28
 
29
 require (
29
 require (
30
 	github.com/pelletier/go-toml/v2 v2.2.4
30
 	github.com/pelletier/go-toml/v2 v2.2.4
31
+	github.com/pires/go-proxyproto v0.11.0
31
 	github.com/txthinking/socks5 v0.0.0-20251011041537-5c31f201a10e
32
 	github.com/txthinking/socks5 v0.0.0-20251011041537-5c31f201a10e
32
 	github.com/yl2chen/cidranger v1.0.2
33
 	github.com/yl2chen/cidranger v1.0.2
33
 )
34
 )

+ 2
- 0
go.sum Просмотреть файл

57
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
57
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
58
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
58
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
59
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
59
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
60
+github.com/pires/go-proxyproto v0.11.0 h1:gUQpS85X/VJMdUsYyEgyn59uLJvGqPhJV5YvG68wXH4=
61
+github.com/pires/go-proxyproto v0.11.0/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
60
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
62
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
61
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
63
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
62
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
64
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

+ 4
- 10
internal/cli/access.go Просмотреть файл

61
 	}
61
 	}
62
 
62
 
63
 	wg := &sync.WaitGroup{}
63
 	wg := &sync.WaitGroup{}
64
-	wg.Add(2)
65
-
66
-	go func() {
67
-		defer wg.Done()
68
 
64
 
65
+	wg.Go(func() {
69
 		ip := a.PublicIPv4
66
 		ip := a.PublicIPv4
70
 		if ip == nil {
67
 		if ip == nil {
71
 			ip = a.getIP(ntw, "tcp4")
68
 			ip = a.getIP(ntw, "tcp4")
76
 		}
73
 		}
77
 
74
 
78
 		resp.IPv4 = a.makeURLs(conf, ip)
75
 		resp.IPv4 = a.makeURLs(conf, ip)
79
-	}()
80
-
81
-	go func() {
82
-		defer wg.Done()
83
-
76
+	})
77
+	wg.Go(func() {
84
 		ip := a.PublicIPv6
78
 		ip := a.PublicIPv6
85
 		if ip == nil {
79
 		if ip == nil {
86
 			ip = a.getIP(ntw, "tcp6")
80
 			ip = a.getIP(ntw, "tcp6")
91
 		}
85
 		}
92
 
86
 
93
 		resp.IPv6 = a.makeURLs(conf, ip)
87
 		resp.IPv6 = a.makeURLs(conf, ip)
94
-	}()
88
+	})
95
 
89
 
96
 	wg.Wait()
90
 	wg.Wait()
97
 
91
 

+ 10
- 0
internal/cli/run_proxy.go Просмотреть файл

10
 	"github.com/9seconds/mtg/v2/antireplay"
10
 	"github.com/9seconds/mtg/v2/antireplay"
11
 	"github.com/9seconds/mtg/v2/events"
11
 	"github.com/9seconds/mtg/v2/events"
12
 	"github.com/9seconds/mtg/v2/internal/config"
12
 	"github.com/9seconds/mtg/v2/internal/config"
13
+	"github.com/9seconds/mtg/v2/internal/proxyprotocol"
13
 	"github.com/9seconds/mtg/v2/internal/utils"
14
 	"github.com/9seconds/mtg/v2/internal/utils"
14
 	"github.com/9seconds/mtg/v2/ipblocklist"
15
 	"github.com/9seconds/mtg/v2/ipblocklist"
15
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
16
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
17
 	"github.com/9seconds/mtg/v2/mtglib"
18
 	"github.com/9seconds/mtg/v2/mtglib"
18
 	"github.com/9seconds/mtg/v2/network"
19
 	"github.com/9seconds/mtg/v2/network"
19
 	"github.com/9seconds/mtg/v2/stats"
20
 	"github.com/9seconds/mtg/v2/stats"
21
+	"github.com/pires/go-proxyproto"
20
 	"github.com/rs/zerolog"
22
 	"github.com/rs/zerolog"
21
 	"github.com/yl2chen/cidranger"
23
 	"github.com/yl2chen/cidranger"
22
 )
24
 )
275
 		return fmt.Errorf("cannot start proxy: %w", err)
277
 		return fmt.Errorf("cannot start proxy: %w", err)
276
 	}
278
 	}
277
 
279
 
280
+	if conf.ProxyProtocolListener.Get(false) {
281
+		listener = &proxyprotocol.ListenerAdapter{
282
+			Listener: proxyproto.Listener{
283
+				Listener: listener,
284
+			},
285
+		}
286
+	}
287
+
278
 	ctx := utils.RootContext()
288
 	ctx := utils.RootContext()
279
 
289
 
280
 	go proxy.Serve(listener) //nolint: errcheck
290
 	go proxy.Serve(listener) //nolint: errcheck

+ 1
- 0
internal/config/config.go Просмотреть файл

25
 	AllowFallbackOnUnknownDC TypeBool        `json:"allowFallbackOnUnknownDc"`
25
 	AllowFallbackOnUnknownDC TypeBool        `json:"allowFallbackOnUnknownDc"`
26
 	Secret                   mtglib.Secret   `json:"secret"`
26
 	Secret                   mtglib.Secret   `json:"secret"`
27
 	BindTo                   TypeHostPort    `json:"bindTo"`
27
 	BindTo                   TypeHostPort    `json:"bindTo"`
28
+	ProxyProtocolListener    TypeBool        `json:"proxyProtocolListener"`
28
 	PreferIP                 TypePreferIP    `json:"preferIp"`
29
 	PreferIP                 TypePreferIP    `json:"preferIp"`
29
 	DomainFrontingPort       TypePort        `json:"domainFrontingPort"`
30
 	DomainFrontingPort       TypePort        `json:"domainFrontingPort"`
30
 	TolerateTimeSkewness     TypeDuration    `json:"tolerateTimeSkewness"`
31
 	TolerateTimeSkewness     TypeDuration    `json:"tolerateTimeSkewness"`

+ 1
- 0
internal/config/parse.go Просмотреть файл

13
 	AllowFallbackOnUnknownDC bool   `toml:"allow-fallback-on-unknown-dc" json:"allowFallbackOnUnknownDc,omitempty"`
13
 	AllowFallbackOnUnknownDC bool   `toml:"allow-fallback-on-unknown-dc" json:"allowFallbackOnUnknownDc,omitempty"`
14
 	Secret                   string `toml:"secret" json:"secret"`
14
 	Secret                   string `toml:"secret" json:"secret"`
15
 	BindTo                   string `toml:"bind-to" json:"bindTo"`
15
 	BindTo                   string `toml:"bind-to" json:"bindTo"`
16
+	ProxyProtocolListener    bool   `toml:"proxy-protocol-listener" json:"proxyProtocolListener"`
16
 	PreferIP                 string `toml:"prefer-ip" json:"preferIp,omitempty"`
17
 	PreferIP                 string `toml:"prefer-ip" json:"preferIp,omitempty"`
17
 	DomainFrontingPort       uint   `toml:"domain-fronting-port" json:"domainFrontingPort,omitempty"`
18
 	DomainFrontingPort       uint   `toml:"domain-fronting-port" json:"domainFrontingPort,omitempty"`
18
 	TolerateTimeSkewness     string `toml:"tolerate-time-skewness" json:"tolerateTimeSkewness,omitempty"`
19
 	TolerateTimeSkewness     string `toml:"tolerate-time-skewness" json:"tolerateTimeSkewness,omitempty"`

+ 2
- 2
internal/config/type_bool_test.go Просмотреть файл

20
 }
20
 }
21
 
21
 
22
 func (suite *TypeBoolTestSuite) TestUnmarshalFail() {
22
 func (suite *TypeBoolTestSuite) TestUnmarshalFail() {
23
-	testData := []interface{}{
23
+	testData := []any{
24
 		"",
24
 		"",
25
 		"np",
25
 		"np",
26
 		"нет",
26
 		"нет",
29
 	}
29
 	}
30
 
30
 
31
 	for _, v := range testData {
31
 	for _, v := range testData {
32
-		data, err := json.Marshal(map[string]interface{}{
32
+		data, err := json.Marshal(map[string]any{
33
 			"value": v,
33
 			"value": v,
34
 		})
34
 		})
35
 		suite.NoError(err)
35
 		suite.NoError(err)

+ 20
- 0
internal/proxyprotocol/adapter.go Просмотреть файл

1
+package proxyprotocol
2
+
3
+import (
4
+	"net"
5
+
6
+	"github.com/pires/go-proxyproto"
7
+)
8
+
9
+type ListenerAdapter struct {
10
+	proxyproto.Listener
11
+}
12
+
13
+func (l *ListenerAdapter) Accept() (net.Conn, error) {
14
+	conn, err := l.Listener.Accept()
15
+	if err != nil {
16
+		return nil, err
17
+	}
18
+
19
+	return connWrapper{conn.(*proxyproto.Conn)}, nil
20
+}

+ 25
- 0
internal/proxyprotocol/conn.go Просмотреть файл

1
+package proxyprotocol
2
+
3
+import "github.com/pires/go-proxyproto"
4
+
5
+type connWrapper struct {
6
+	*proxyproto.Conn
7
+}
8
+
9
+func (c connWrapper) CloseRead() error {
10
+	tcpConn, ok := c.TCPConn()
11
+	if !ok {
12
+		panic("we support only tcp connections")
13
+	}
14
+
15
+	return tcpConn.CloseRead()
16
+}
17
+
18
+func (c connWrapper) CloseWrite() error {
19
+	tcpConn, ok := c.TCPConn()
20
+	if !ok {
21
+		panic("we support only tcp connections")
22
+	}
23
+
24
+	return tcpConn.CloseWrite()
25
+}

+ 4
- 7
ipblocklist/firehol.go Просмотреть файл

112
 	defer cancel()
112
 	defer cancel()
113
 
113
 
114
 	wg := &sync.WaitGroup{}
114
 	wg := &sync.WaitGroup{}
115
-	wg.Add(len(f.blocklists))
116
 
115
 
117
 	mutex := &sync.Mutex{}
116
 	mutex := &sync.Mutex{}
118
 	ranger := cidranger.NewPCTrieRanger()
117
 	ranger := cidranger.NewPCTrieRanger()
119
 
118
 
120
 	for _, v := range f.blocklists {
119
 	for _, v := range f.blocklists {
121
-		go func(file files.File) {
122
-			defer wg.Done()
120
+		wg.Go(func() {
121
+			logger := f.logger.BindStr("filename", v.String())
123
 
122
 
124
-			logger := f.logger.BindStr("filename", file.String())
125
-
126
-			fileContent, err := file.Open(ctx)
123
+			fileContent, err := v.Open(ctx)
127
 			if err != nil {
124
 			if err != nil {
128
 				logger.WarningError("update has failed", err)
125
 				logger.WarningError("update has failed", err)
129
 
126
 
135
 			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
132
 			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
136
 				logger.WarningError("update has failed", err)
133
 				logger.WarningError("update has failed", err)
137
 			}
134
 			}
138
-		}(v)
135
+		})
139
 	}
136
 	}
140
 
137
 
141
 	wg.Wait()
138
 	wg.Wait()

+ 1
- 1
logger/init.go Просмотреть файл

8
 // commonly used by many 3pp tools. While mtglib itself does not need it, it is
8
 // commonly used by many 3pp tools. While mtglib itself does not need it, it is
9
 // always a good idea to support it and have a transient end to end logging.
9
 // always a good idea to support it and have a transient end to end logging.
10
 type StdLikeLogger interface {
10
 type StdLikeLogger interface {
11
-	Printf(format string, args ...interface{})
11
+	Printf(format string, args ...any)
12
 }
12
 }

+ 1
- 1
logger/noop.go Просмотреть файл

8
 func (n noopLogger) BindInt(_ string, _ int) mtglib.Logger { return n }
8
 func (n noopLogger) BindInt(_ string, _ int) mtglib.Logger { return n }
9
 func (n noopLogger) BindStr(_, _ string) mtglib.Logger     { return n }
9
 func (n noopLogger) BindStr(_, _ string) mtglib.Logger     { return n }
10
 func (n noopLogger) BindJSON(_, _ string) mtglib.Logger    { return n }
10
 func (n noopLogger) BindJSON(_, _ string) mtglib.Logger    { return n }
11
-func (n noopLogger) Printf(_ string, _ ...interface{})     {}
11
+func (n noopLogger) Printf(_ string, _ ...any)             {}
12
 func (n noopLogger) Info(_ string)                         {}
12
 func (n noopLogger) Info(_ string)                         {}
13
 func (n noopLogger) Warning(_ string)                      {}
13
 func (n noopLogger) Warning(_ string)                      {}
14
 func (n noopLogger) Debug(_ string)                        {}
14
 func (n noopLogger) Debug(_ string)                        {}

+ 1
- 1
logger/zerolog.go Просмотреть файл

78
 	}
78
 	}
79
 }
79
 }
80
 
80
 
81
-func (z *zeroLogContext) Printf(format string, args ...interface{}) {
81
+func (z *zeroLogContext) Printf(format string, args ...any) {
82
 	z.Debug(fmt.Sprintf(format, args...))
82
 	z.Debug(fmt.Sprintf(format, args...))
83
 }
83
 }
84
 
84
 

+ 23
- 1
mise.lock Просмотреть файл

7
 "platforms.macos-x64" = { checksum = "sha256:1ca28b7703cbea05a65b2a1d92d6b308610ef92f8824578a0874f2e60c9d5a22", url = "https://dl.google.com/go/go1.26.0.darwin-amd64.tar.gz"}
7
 "platforms.macos-x64" = { checksum = "sha256:1ca28b7703cbea05a65b2a1d92d6b308610ef92f8824578a0874f2e60c9d5a22", url = "https://dl.google.com/go/go1.26.0.darwin-amd64.tar.gz"}
8
 "platforms.windows-x64" = { checksum = "sha256:9bbe0fc64236b2b51f6255c05c4232532b8ecc0e6d2e00950bd3021d8a4d07d4", url = "https://dl.google.com/go/go1.26.0.windows-amd64.zip"}
8
 "platforms.windows-x64" = { checksum = "sha256:9bbe0fc64236b2b51f6255c05c4232532b8ecc0e6d2e00950bd3021d8a4d07d4", url = "https://dl.google.com/go/go1.26.0.windows-amd64.zip"}
9
 
9
 
10
+[[tools."go:golang.org/x/pkgsite/cmd/pkgsite"]]
11
+version = "latest"
12
+backend = "go:golang.org/x/pkgsite/cmd/pkgsite"
13
+
10
 [[tools."go:golang.org/x/tools/gopls"]]
14
 [[tools."go:golang.org/x/tools/gopls"]]
11
-version = "0.21.0"
15
+version = "0.21.1"
12
 backend = "go:golang.org/x/tools/gopls"
16
 backend = "go:golang.org/x/tools/gopls"
13
 
17
 
14
 [[tools."go:mvdan.cc/gofumpt"]]
18
 [[tools."go:mvdan.cc/gofumpt"]]
15
 version = "0.9.2"
19
 version = "0.9.2"
16
 backend = "go:mvdan.cc/gofumpt"
20
 backend = "go:mvdan.cc/gofumpt"
21
+
22
+[[tools.golangci-lint]]
23
+version = "2.10.1"
24
+backend = "aqua:golangci/golangci-lint"
25
+"platforms.linux-arm64" = { checksum = "sha256:6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-linux-arm64.tar.gz"}
26
+"platforms.linux-x64" = { checksum = "sha256:dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-linux-amd64.tar.gz"}
27
+"platforms.macos-arm64" = { checksum = "sha256:03bfadf67e52b441b7ec21305e501c717df93c959836d66c7f97312654acb297", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-darwin-arm64.tar.gz"}
28
+"platforms.macos-x64" = { checksum = "sha256:66fb0da81b8033b477f97eea420d4b46b230ca172b8bb87c6610109f3772b6b6", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-darwin-amd64.tar.gz"}
29
+"platforms.windows-x64" = { checksum = "sha256:c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-windows-amd64.zip"}
30
+
31
+[[tools.goreleaser]]
32
+version = "2.13.3"
33
+backend = "aqua:goreleaser/goreleaser"
34
+"platforms.linux-arm64" = { checksum = "sha256:156656d0f874542d618568bd50afd3d33ced2e8aab2c60cc7c21e1b9fa52031e", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_arm64.tar.gz"}
35
+"platforms.linux-x64" = { checksum = "sha256:4b66f2f78f78561330350651ade557b70328664718490f37834749073af21d20", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_x86_64.tar.gz"}
36
+"platforms.macos-arm64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"}
37
+"platforms.macos-x64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"}
38
+"platforms.windows-x64" = { checksum = "sha256:c5586c4ed749ca358ad61ed73ee4b8039cfa68daae8c23e69fb086d549dfb31d", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Windows_x86_64.zip"}

+ 1
- 1
mtglib/init.go Просмотреть файл

249
 	BindJSON(name, value string) Logger
249
 	BindJSON(name, value string) Logger
250
 
250
 
251
 	// Printf is to support log.Logger behavior.
251
 	// Printf is to support log.Logger behavior.
252
-	Printf(format string, args ...interface{})
252
+	Printf(format string, args ...any)
253
 
253
 
254
 	// Info puts a message about some normal situation.
254
 	// Info puts a message about some normal situation.
255
 	Info(msg string)
255
 	Info(msg string)

+ 11
- 11
mtglib/init_internal_test.go Просмотреть файл

8
 
8
 
9
 type NoopLogger struct{}
9
 type NoopLogger struct{}
10
 
10
 
11
-func (n NoopLogger) Named(_ string) Logger             { return n }
12
-func (n NoopLogger) BindInt(_ string, _ int) Logger    { return n }
13
-func (n NoopLogger) BindStr(_, _ string) Logger        { return n }
14
-func (n NoopLogger) BindJSON(_, _ string) Logger       { return n }
15
-func (n NoopLogger) Printf(_ string, _ ...interface{}) {}
16
-func (n NoopLogger) Info(_ string)                     {}
17
-func (n NoopLogger) Warning(_ string)                  {}
18
-func (n NoopLogger) Debug(_ string)                    {}
19
-func (n NoopLogger) InfoError(_ string, _ error)       {}
20
-func (n NoopLogger) WarningError(_ string, _ error)    {}
21
-func (n NoopLogger) DebugError(_ string, _ error)      {}
11
+func (n NoopLogger) Named(_ string) Logger          { return n }
12
+func (n NoopLogger) BindInt(_ string, _ int) Logger { return n }
13
+func (n NoopLogger) BindStr(_, _ string) Logger     { return n }
14
+func (n NoopLogger) BindJSON(_, _ string) Logger    { return n }
15
+func (n NoopLogger) Printf(_ string, _ ...any)      {}
16
+func (n NoopLogger) Info(_ string)                  {}
17
+func (n NoopLogger) Warning(_ string)               {}
18
+func (n NoopLogger) Debug(_ string)                 {}
19
+func (n NoopLogger) InfoError(_ string, _ error)    {}
20
+func (n NoopLogger) WarningError(_ string, _ error) {}
21
+func (n NoopLogger) DebugError(_ string, _ error)   {}
22
 
22
 
23
 type EventStreamMock struct {
23
 type EventStreamMock struct {
24
 	mock.Mock
24
 	mock.Mock

+ 1
- 1
mtglib/internal/faketls/client_hello.go Просмотреть файл

76
 
76
 
77
 	computedRandom := mac.Sum(nil)
77
 	computedRandom := mac.Sum(nil)
78
 
78
 
79
-	for i := 0; i < RandomLen; i++ {
79
+	for i := range RandomLen {
80
 		computedRandom[i] ^= hello.Random[i]
80
 		computedRandom[i] ^= hello.Random[i]
81
 	}
81
 	}
82
 
82
 

+ 2
- 2
mtglib/internal/faketls/conn.go Просмотреть файл

3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 
7
 
8
 	"github.com/9seconds/mtg/v2/essentials"
8
 	"github.com/9seconds/mtg/v2/essentials"
9
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
9
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
53
 	lenP := len(p)
53
 	lenP := len(p)
54
 
54
 
55
 	for len(p) > 0 {
55
 	for len(p) > 0 {
56
-		chunkSize := rand.Intn(record.TLSMaxRecordSize)
56
+		chunkSize := rand.IntN(record.TLSMaxRecordSize)
57
 		if chunkSize > len(p) || chunkSize == 0 {
57
 		if chunkSize > len(p) || chunkSize == 0 {
58
 			chunkSize = len(p)
58
 			chunkSize = len(p)
59
 		}
59
 		}

+ 2
- 2
mtglib/internal/faketls/conn_test.go Просмотреть файл

2
 
2
 
3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
+	"crypto/rand"
5
 	"errors"
6
 	"errors"
6
 	"io"
7
 	"io"
7
-	"math/rand"
8
 	"testing"
8
 	"testing"
9
 
9
 
10
 	"github.com/9seconds/mtg/v2/internal/testlib"
10
 	"github.com/9seconds/mtg/v2/internal/testlib"
123
 	suite.connMock.On("Write", mock.Anything).Return(0, nil)
123
 	suite.connMock.On("Write", mock.Anything).Return(0, nil)
124
 
124
 
125
 	dataToRec := make([]byte, record.TLSMaxRecordSize*2)
125
 	dataToRec := make([]byte, record.TLSMaxRecordSize*2)
126
-	rand.Read(dataToRec) //nolint: staticcheck
126
+	rand.Read(dataToRec) //nolint: staticcheck, errcheck
127
 
127
 
128
 	n, err := suite.c.Write(dataToRec)
128
 	n, err := suite.c.Write(dataToRec)
129
 	suite.NoError(err)
129
 	suite.NoError(err)

+ 1
- 1
mtglib/internal/faketls/pools.go Просмотреть файл

6
 )
6
 )
7
 
7
 
8
 var bytesBufferPool = sync.Pool{
8
 var bytesBufferPool = sync.Pool{
9
-	New: func() interface{} {
9
+	New: func() any {
10
 		return &bytes.Buffer{}
10
 		return &bytes.Buffer{}
11
 	},
11
 	},
12
 }
12
 }

+ 1
- 1
mtglib/internal/faketls/record/pools.go Просмотреть файл

5
 )
5
 )
6
 
6
 
7
 var recordPool = sync.Pool{
7
 var recordPool = sync.Pool{
8
-	New: func() interface{} {
8
+	New: func() any {
9
 		return &Record{}
9
 		return &Record{}
10
 	},
10
 	},
11
 }
11
 }

+ 2
- 2
mtglib/internal/faketls/welcome.go Просмотреть файл

6
 	"crypto/sha256"
6
 	"crypto/sha256"
7
 	"encoding/binary"
7
 	"encoding/binary"
8
 	"io"
8
 	"io"
9
-	mrand "math/rand"
9
+	mrand "math/rand/v2"
10
 
10
 
11
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
11
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
12
 	"golang.org/x/crypto/curve25519"
12
 	"golang.org/x/crypto/curve25519"
36
 	rec.Type = record.TypeApplicationData
36
 	rec.Type = record.TypeApplicationData
37
 	rec.Version = record.Version12
37
 	rec.Version = record.Version12
38
 
38
 
39
-	if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.Intn(3092))); err != nil {
39
+	if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.IntN(3092))); err != nil {
40
 		panic(err)
40
 		panic(err)
41
 	}
41
 	}
42
 
42
 

+ 1
- 1
mtglib/internal/faketls/welcome_test.go Просмотреть файл

3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
 	"crypto/hmac"
5
 	"crypto/hmac"
6
+	"crypto/rand"
6
 	"crypto/sha256"
7
 	"crypto/sha256"
7
-	"math/rand"
8
 	"testing"
8
 	"testing"
9
 	"time"
9
 	"time"
10
 
10
 

+ 1
- 1
mtglib/internal/obfuscated2/handshake_frame.go Просмотреть файл

63
 func (h *handshakeFrame) invert() handshakeFrame {
63
 func (h *handshakeFrame) invert() handshakeFrame {
64
 	copyFrame := *h
64
 	copyFrame := *h
65
 
65
 
66
-	for i := 0; i < handshakeFrameLenKey+handshakeFrameLenIV; i++ {
66
+	for i := range handshakeFrameLenKey + handshakeFrameLenIV {
67
 		copyFrame.data[handshakeFrameOffsetKey+i] = h.data[handshakeFrameOffsetConnectionType-1-i]
67
 		copyFrame.data[handshakeFrameOffsetKey+i] = h.data[handshakeFrameOffsetConnectionType-1-i]
68
 	}
68
 	}
69
 
69
 

+ 1
- 1
mtglib/internal/obfuscated2/init_test.go Просмотреть файл

117
 
117
 
118
 	serverEncryptedReverted := make([]byte, len(serverEncrypted))
118
 	serverEncryptedReverted := make([]byte, len(serverEncrypted))
119
 
119
 
120
-	for i := 0; i < 32+16; i++ {
120
+	for i := range 32 + 16 {
121
 		serverEncryptedReverted[8+i] = serverEncrypted[8+32+16-1-i]
121
 		serverEncryptedReverted[8+i] = serverEncrypted[8+32+16-1-i]
122
 	}
122
 	}
123
 
123
 

+ 2
- 2
mtglib/internal/obfuscated2/pools.go Просмотреть файл

9
 
9
 
10
 var (
10
 var (
11
 	sha256HasherPool = sync.Pool{
11
 	sha256HasherPool = sync.Pool{
12
-		New: func() interface{} {
12
+		New: func() any {
13
 			return sha256.New()
13
 			return sha256.New()
14
 		},
14
 		},
15
 	}
15
 	}
16
 	bytesBufferPool = sync.Pool{
16
 	bytesBufferPool = sync.Pool{
17
-		New: func() interface{} {
17
+		New: func() any {
18
 			return &bytes.Buffer{}
18
 			return &bytes.Buffer{}
19
 		},
19
 		},
20
 	}
20
 	}

+ 1
- 1
mtglib/internal/relay/init.go Просмотреть файл

5
 )
5
 )
6
 
6
 
7
 type Logger interface {
7
 type Logger interface {
8
-	Printf(msg string, args ...interface{})
8
+	Printf(msg string, args ...any)
9
 }
9
 }

+ 1
- 1
mtglib/internal/relay/init_test.go Просмотреть файл

2
 
2
 
3
 type loggerMock struct{}
3
 type loggerMock struct{}
4
 
4
 
5
-func (l loggerMock) Printf(format string, args ...interface{}) {}
5
+func (l loggerMock) Printf(format string, args ...any) {}

+ 1
- 1
mtglib/internal/relay/pools.go Просмотреть файл

3
 import "sync"
3
 import "sync"
4
 
4
 
5
 var copyBufferPool = sync.Pool{
5
 var copyBufferPool = sync.Pool{
6
-	New: func() interface{} {
6
+	New: func() any {
7
 		rv := make([]byte, copyBufferSize)
7
 		rv := make([]byte, copyBufferSize)
8
 
8
 
9
 		return &rv
9
 		return &rv

+ 1
- 1
mtglib/proxy.go Просмотреть файл

323
 	}
323
 	}
324
 
324
 
325
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
325
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
326
-		func(arg interface{}) {
326
+		func(arg any) {
327
 			proxy.ServeConn(arg.(essentials.Conn)) //nolint: forcetypeassert
327
 			proxy.ServeConn(arg.(essentials.Conn)) //nolint: forcetypeassert
328
 		},
328
 		},
329
 		ants.WithLogger(opts.getLogger("ants")),
329
 		ants.WithLogger(opts.getLogger("ants")),

+ 1
- 1
mtglib/stream_context.go Просмотреть файл

32
 	return s.ctx.Err() //nolint: wrapcheck
32
 	return s.ctx.Err() //nolint: wrapcheck
33
 }
33
 }
34
 
34
 
35
-func (s *streamContext) Value(key interface{}) interface{} {
35
+func (s *streamContext) Value(key any) any {
36
 	return s.ctx.Value(key)
36
 	return s.ctx.Value(key)
37
 }
37
 }
38
 
38
 

+ 8
- 11
network/circuit_breaker_internal_test.go Просмотреть файл

52
 		Return(suite.connMock, nil)
52
 		Return(suite.connMock, nil)
53
 
53
 
54
 	wg := &sync.WaitGroup{}
54
 	wg := &sync.WaitGroup{}
55
-	wg.Add(5)
56
-
57
-	go func() {
58
-		wg.Wait()
59
-		suite.ctxCancel()
60
-	}()
61
-
62
-	for i := 0; i < 5; i++ {
63
-		go func() {
64
-			defer wg.Done()
65
 
55
 
56
+	for range 5 {
57
+		wg.Go(func() {
66
 			conn, err := suite.d.DialContext(suite.ctx, "tcp", "127.0.0.1")
58
 			conn, err := suite.d.DialContext(suite.ctx, "tcp", "127.0.0.1")
67
 
59
 
68
 			suite.mutex.Lock()
60
 			suite.mutex.Lock()
70
 
62
 
71
 			suite.NoError(err)
63
 			suite.NoError(err)
72
 			suite.Equal("127.0.0.1:3128", conn.RemoteAddr().String())
64
 			suite.Equal("127.0.0.1:3128", conn.RemoteAddr().String())
73
-		}()
65
+		})
74
 	}
66
 	}
75
 
67
 
68
+	go func() {
69
+		wg.Wait()
70
+		suite.ctxCancel()
71
+	}()
72
+
76
 	suite.Eventually(func() bool {
73
 	suite.Eventually(func() bool {
77
 		_, ok := <-suite.ctx.Done()
74
 		_, ok := <-suite.ctx.Done()
78
 
75
 

+ 2
- 2
network/load_balanced_socks5.go Просмотреть файл

3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 	"net/url"
7
 	"net/url"
8
 
8
 
9
 	"github.com/9seconds/mtg/v2/essentials"
9
 	"github.com/9seconds/mtg/v2/essentials"
19
 
19
 
20
 func (l loadBalancedSocks5Dialer) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
20
 func (l loadBalancedSocks5Dialer) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
21
 	length := len(l.dialers)
21
 	length := len(l.dialers)
22
-	start := rand.Intn(length)
22
+	start := rand.IntN(length)
23
 	moved := false
23
 	moved := false
24
 
24
 
25
 	for i := start; i != start || !moved; i = (i + 1) % length {
25
 	for i := start; i != start || !moved; i = (i + 1) % length {

+ 1
- 1
network/load_balanced_socks5_test.go Просмотреть файл

64
 	})
64
 	})
65
 	suite.NoError(err)
65
 	suite.NoError(err)
66
 
66
 
67
-	for i := 0; i < network.ProxyDialerOpenThreshold*2; i++ {
67
+	for range network.ProxyDialerOpenThreshold * 2 {
68
 		_, err = lbDialer.Dial("tcp", "127.1.1.1:80")
68
 		_, err = lbDialer.Dial("tcp", "127.1.1.1:80")
69
 		suite.True(errors.Is(err, network.ErrCannotDialWithAllProxies))
69
 		suite.True(errors.Is(err, network.ErrCannotDialWithAllProxies))
70
 	}
70
 	}

+ 5
- 13
network/network.go Просмотреть файл

3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 	"net"
7
 	"net"
8
 	"net/http"
8
 	"net/http"
9
 	"sync"
9
 	"sync"
81
 
81
 
82
 	switch protocol {
82
 	switch protocol {
83
 	case "tcp", "tcp4":
83
 	case "tcp", "tcp4":
84
-		wg.Add(1)
85
-
86
-		go func() {
87
-			defer wg.Done()
88
-
84
+		wg.Go(func() {
89
 			resolved := n.dns.LookupA(address)
85
 			resolved := n.dns.LookupA(address)
90
 
86
 
91
 			mutex.Lock()
87
 			mutex.Lock()
92
 			ips = append(ips, resolved...)
88
 			ips = append(ips, resolved...)
93
 			mutex.Unlock()
89
 			mutex.Unlock()
94
-		}()
90
+		})
95
 	}
91
 	}
96
 
92
 
97
 	switch protocol {
93
 	switch protocol {
98
 	case "tcp", "tcp6":
94
 	case "tcp", "tcp6":
99
-		wg.Add(1)
100
-
101
-		go func() {
102
-			defer wg.Done()
103
-
95
+		wg.Go(func() {
104
 			resolved := n.dns.LookupAAAA(address)
96
 			resolved := n.dns.LookupAAAA(address)
105
 
97
 
106
 			mutex.Lock()
98
 			mutex.Lock()
107
 			ips = append(ips, resolved...)
99
 			ips = append(ips, resolved...)
108
 			mutex.Unlock()
100
 			mutex.Unlock()
109
-		}()
101
+		})
110
 	}
102
 	}
111
 
103
 
112
 	wg.Wait()
104
 	wg.Wait()

+ 1
- 1
stats/pools.go Просмотреть файл

3
 import "sync"
3
 import "sync"
4
 
4
 
5
 var streamInfoPool = sync.Pool{
5
 var streamInfoPool = sync.Pool{
6
-	New: func() interface{} {
6
+	New: func() any {
7
 		return &streamInfo{
7
 		return &streamInfo{
8
 			tags: make(map[string]string),
8
 			tags: make(map[string]string),
9
 		}
9
 		}

Загрузка…
Отмена
Сохранить