Kaynağa Gözat

Merge remote-tracking branch 'origin/master' into stable

tags/v2.1.2
9seconds 4 yıl önce
ebeveyn
işleme
929b73e2eb

+ 3
- 2
.github/workflows/ci.yaml Dosyayı Görüntüle

@@ -30,7 +30,8 @@ jobs:
30 30
     strategy:
31 31
       matrix:
32 32
         go_version:
33
-          - ^1.16
33
+          - ~1.16
34
+          - ^1.17
34 35
     steps:
35 36
       - name: Checkout
36 37
         uses: actions/checkout@v2
@@ -70,7 +71,7 @@ jobs:
70 71
       - name: Run linter
71 72
         uses: golangci/golangci-lint-action@v2
72 73
         with:
73
-          version: v1.41.1
74
+          version: v1.42.0
74 75
 
75 76
   docker:
76 77
     name: Docker

+ 1
- 1
Dockerfile Dosyayı Görüntüle

@@ -1,7 +1,7 @@
1 1
 ###############################################################################
2 2
 # BUILD STAGE
3 3
 
4
-FROM golang:1.16-alpine AS build
4
+FROM golang:1.17-alpine AS build
5 5
 
6 6
 RUN set -x \
7 7
   && apk --no-cache --update add \

+ 1
- 1
Makefile Dosyayı Görüntüle

@@ -2,7 +2,7 @@ ROOT_DIR     := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
2 2
 IMAGE_NAME   := mtg
3 3
 APP_NAME     := $(IMAGE_NAME)
4 4
 
5
-GOLANGCI_LINT_VERSION := v1.41.1
5
+GOLANGCI_LINT_VERSION := v1.42.0
6 6
 
7 7
 VERSION_GO         := $(shell go version)
8 8
 VERSION_DATE       := $(shell date -Ru)

+ 22
- 4
go.mod Dosyayı Görüntüle

@@ -1,6 +1,6 @@
1 1
 module github.com/9seconds/mtg/v2
2 2
 
3
-go 1.16
3
+go 1.17
4 4
 
5 5
 require (
6 6
 	github.com/OneOfOne/xxhash v1.2.8
@@ -13,14 +13,13 @@ require (
13 13
 	github.com/gotd/td v0.34.0
14 14
 	github.com/jarcoal/httpmock v1.0.8
15 15
 	github.com/kentik/patricia v0.0.0-20201202224819-f9447a6e25f1
16
-	github.com/libp2p/go-reuseport v0.0.2
17 16
 	github.com/mccutchen/go-httpbin v1.1.1
18 17
 	github.com/panjf2000/ants/v2 v2.4.6
19 18
 	github.com/pelletier/go-toml v1.9.3
20 19
 	github.com/prometheus/client_golang v1.11.0
21 20
 	github.com/prometheus/common v0.30.0 // indirect
22
-	github.com/prometheus/procfs v0.7.1 // indirect
23
-	github.com/rs/zerolog v1.23.0
21
+	github.com/prometheus/procfs v0.7.3 // indirect
22
+	github.com/rs/zerolog v1.24.0
24 23
 	github.com/smira/go-statsd v1.3.2
25 24
 	github.com/stretchr/objx v0.3.0 // indirect
26 25
 	github.com/stretchr/testify v1.7.0
@@ -30,3 +29,22 @@ require (
30 29
 	golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
31 30
 	google.golang.org/protobuf v1.27.1 // indirect
32 31
 )
32
+
33
+require (
34
+	github.com/beorn7/perks v1.0.1 // indirect
35
+	github.com/cenkalti/backoff/v4 v4.1.0 // indirect
36
+	github.com/cespare/xxhash/v2 v2.1.2 // indirect
37
+	github.com/davecgh/go-spew v1.1.1 // indirect
38
+	github.com/gotd/ige v0.1.5 // indirect
39
+	github.com/gotd/xor v0.1.1 // indirect
40
+	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
41
+	github.com/pkg/errors v0.9.1 // indirect
42
+	github.com/pmezard/go-difflib v1.0.0 // indirect
43
+	github.com/prometheus/client_model v0.2.0 // indirect
44
+	go.uber.org/atomic v1.7.0 // indirect
45
+	go.uber.org/multierr v1.6.0 // indirect
46
+	go.uber.org/zap v1.16.0 // indirect
47
+	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
48
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
49
+	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
50
+)

+ 17
- 17
go.sum Dosyayı Görüntüle

@@ -59,8 +59,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
59 59
 github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc=
60 60
 github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
61 61
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
62
-github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
63 62
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
63
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
64
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
64 65
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
65 66
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
66 67
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -179,8 +180,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
179 180
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
180 181
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
181 182
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
182
-github.com/libp2p/go-reuseport v0.0.2 h1:XSG94b1FJfGA01BUrT82imejHQyTxO4jEWqheyCXYvU=
183
-github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ=
184 183
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
185 184
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
186 185
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
@@ -224,14 +223,14 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
224 223
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
225 224
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
226 225
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
227
-github.com/prometheus/procfs v0.7.1 h1:TlEtJq5GvGqMykEwWzbZWjjztF86swFhsPix1i0bkgA=
228
-github.com/prometheus/procfs v0.7.1/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
226
+github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
227
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
229 228
 github.com/quasilyte/go-ruleguard/dsl v0.3.2/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
230 229
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
231 230
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
232
-github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
233
-github.com/rs/zerolog v1.23.0 h1:UskrK+saS9P9Y789yNNulYKdARjPZuS35B8gJF2x60g=
234
-github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo=
231
+github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
232
+github.com/rs/zerolog v1.24.0 h1:76ivFxmVSRs1u2wUwJVg5VZDYQgeH1JpoS6ndgr9Wy8=
233
+github.com/rs/zerolog v1.24.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI=
235 234
 github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
236 235
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
237 236
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
@@ -248,7 +247,6 @@ github.com/stretchr/testify v1.1.5-0.20170809224252-890a5c3458b4/go.mod h1:a8OnR
248 247
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
249 248
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
250 249
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
251
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
252 250
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
253 251
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
254 252
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -257,7 +255,7 @@ github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43/go.mod h1:O
257 255
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
258 256
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
259 257
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
260
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
258
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
261 259
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
262 260
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
263 261
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -311,8 +309,9 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
311 309
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
312 310
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
313 311
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
314
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
315 312
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
313
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
314
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
316 315
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
317 316
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
318 317
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -344,6 +343,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
344 343
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
345 344
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
346 345
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
346
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
347 347
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
348 348
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8=
349 349
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -361,15 +361,14 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
361 361
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
362 362
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
363 363
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
364
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
365
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
366 364
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
365
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
366
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
367 367
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
368 368
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
369 369
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
370 370
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
371 371
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
372
-golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
373 372
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
374 373
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
375 374
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -400,9 +399,10 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
400 399
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
401 400
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
402 401
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
403
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
404 402
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
403
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
405 404
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
405
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
406 406
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
407 407
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
408 408
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
@@ -460,8 +460,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
460 460
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
461 461
 golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
462 462
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
463
-golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
464
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
463
+golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
464
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
465 465
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
466 466
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
467 467
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

+ 1
- 2
internal/cli/run_proxy.go Dosyayı Görüntüle

@@ -183,7 +183,6 @@ func runProxy(conf *config.Config, version string) error {
183 183
 		Secret:             conf.Secret,
184 184
 		BufferSize:         conf.TCPBuffer.Get(mtglib.DefaultBufferSize),
185 185
 		DomainFrontingPort: conf.DomainFrontingPort.Get(mtglib.DefaultDomainFrontingPort),
186
-		IdleTimeout:        conf.Network.Timeout.Idle.Get(mtglib.DefaultIdleTimeout),
187 186
 		PreferIP:           conf.PreferIP.Get(mtglib.DefaultPreferIP),
188 187
 	}
189 188
 
@@ -192,7 +191,7 @@ func runProxy(conf *config.Config, version string) error {
192 191
 		return fmt.Errorf("cannot create a proxy: %w", err)
193 192
 	}
194 193
 
195
-	listener, err := net.Listen("tcp", conf.BindTo.Get(""))
194
+	listener, err := utils.NewListener(conf.BindTo.Get(""), int(opts.BufferSize))
196 195
 	if err != nil {
197 196
 		return fmt.Errorf("cannot start proxy: %w", err)
198 197
 	}

+ 41
- 0
internal/utils/net_listener.go Dosyayı Görüntüle

@@ -0,0 +1,41 @@
1
+package utils
2
+
3
+import (
4
+	"fmt"
5
+	"net"
6
+
7
+	"github.com/9seconds/mtg/v2/network"
8
+)
9
+
10
+type Listener struct {
11
+	net.Listener
12
+
13
+	bufferSize int
14
+}
15
+
16
+func (l Listener) Accept() (net.Conn, error) {
17
+	conn, err := l.Listener.Accept()
18
+	if err != nil {
19
+		return nil, err // nolint: wrapcheck
20
+	}
21
+
22
+	if err := network.SetClientSocketOptions(conn, l.bufferSize); err != nil {
23
+		conn.Close()
24
+
25
+		return nil, fmt.Errorf("cannot set TCP options: %w", err)
26
+	}
27
+
28
+	return conn, nil
29
+}
30
+
31
+func NewListener(bindTo string, bufferSize int) (net.Listener, error) {
32
+	base, err := net.Listen("tcp", bindTo)
33
+	if err != nil {
34
+		return nil, fmt.Errorf("cannot build a base listener: %w", err)
35
+	}
36
+
37
+	return Listener{
38
+		Listener:   base,
39
+		bufferSize: bufferSize,
40
+	}, nil
41
+}

+ 10
- 2
mtglib/init.go Dosyayı Görüntüle

@@ -69,6 +69,9 @@ const (
69 69
 
70 70
 	// DefaultIdleTimeout is a default timeout for closing a connection
71 71
 	// in case of idling.
72
+	//
73
+	// Deprecated: no longer in use because of changed TCP relay
74
+	// algorithm.
72 75
 	DefaultIdleTimeout = time.Minute
73 76
 
74 77
 	// DefaultTolerateTimeSkewness is a default timeout for time
@@ -83,9 +86,14 @@ const (
83 86
 	// by Telegram and a proxy.
84 87
 	SecretKeyLength = 16
85 88
 
86
-	// ConnectionIDBytesLength defines a count of random bytes
87
-	// used to generate a stream/connection ids.
89
+	// ConnectionIDBytesLength defines a count of random bytes used to generate
90
+	// a stream/connection ids.
88 91
 	ConnectionIDBytesLength = 16
92
+
93
+	// TCPRelayReadTimeout defines a max time period between two consecuitive
94
+	// reads from Telegram after which connection will be terminated. This is
95
+	// required to abort stale connections.
96
+	TCPRelayReadTimeout = 20 * time.Second
89 97
 )
90 98
 
91 99
 // Network defines a knowledge how to work with a network. It may sound

+ 11
- 7
mtglib/internal/faketls/conn.go Dosyayı Görüntüle

@@ -46,7 +46,11 @@ func (c *Conn) Write(p []byte) (int, error) {
46 46
 
47 47
 	rec.Type = record.TypeApplicationData
48 48
 	rec.Version = record.Version12
49
-	written := 0
49
+
50
+	sendBuffer := acquireBytesBuffer()
51
+	defer releaseBytesBuffer(sendBuffer)
52
+
53
+	lenP := len(p)
50 54
 
51 55
 	for len(p) > 0 {
52 56
 		chunkSize := rand.Intn(record.TLSMaxRecordSize)
@@ -56,14 +60,14 @@ func (c *Conn) Write(p []byte) (int, error) {
56 60
 
57 61
 		rec.Payload.Reset()
58 62
 		rec.Payload.Write(p[:chunkSize])
63
+		rec.Dump(sendBuffer) // nolint: errcheck
59 64
 
60
-		if err := rec.Dump(c.Conn); err != nil {
61
-			return written, err // nolint: wrapcheck
62
-		}
63
-
64
-		written += chunkSize
65 65
 		p = p[chunkSize:]
66 66
 	}
67 67
 
68
-	return written, nil
68
+	if _, err := c.Conn.Write(sendBuffer.Bytes()); err != nil {
69
+		return 0, err // nolint: wrapcheck
70
+	}
71
+
72
+	return lenP, nil
69 73
 }

+ 7
- 23
mtglib/internal/relay/conn.go Dosyayı Görüntüle

@@ -1,35 +1,19 @@
1 1
 package relay
2 2
 
3 3
 import (
4
-	"context"
5
-	"io"
4
+	"fmt"
5
+	"net"
6
+	"time"
6 7
 )
7 8
 
8 9
 type conn struct {
9
-	io.ReadWriteCloser
10
-
11
-	ctx         context.Context
12
-	tickChannel chan struct{}
10
+	net.Conn
13 11
 }
14 12
 
15 13
 func (c conn) Read(p []byte) (int, error) {
16
-	n, err := c.ReadWriteCloser.Read(p)
17
-
18
-	select {
19
-	case <-c.ctx.Done():
20
-	case c.tickChannel <- struct{}{}:
21
-	}
22
-
23
-	return n, err // nolint: wrapcheck
24
-}
25
-
26
-func (c conn) Write(p []byte) (int, error) {
27
-	n, err := c.ReadWriteCloser.Write(p)
28
-
29
-	select {
30
-	case <-c.ctx.Done():
31
-	case c.tickChannel <- struct{}{}:
14
+	if err := c.SetReadDeadline(time.Now().Add(getTimeout())); err != nil {
15
+		return 0, fmt.Errorf("cannot set read deadline: %w", err)
32 16
 	}
33 17
 
34
-	return n, err // nolint: wrapcheck
18
+	return c.Conn.Read(p) // nolint: wrapcheck
35 19
 }

+ 0
- 125
mtglib/internal/relay/conn_internal_test.go Dosyayı Görüntüle

@@ -1,125 +0,0 @@
1
-package relay
2
-
3
-import (
4
-	"context"
5
-	"errors"
6
-	"io"
7
-	"testing"
8
-
9
-	"github.com/9seconds/mtg/v2/internal/testlib"
10
-	"github.com/stretchr/testify/mock"
11
-	"github.com/stretchr/testify/suite"
12
-)
13
-
14
-type ConnTestSuite struct {
15
-	suite.Suite
16
-
17
-	ctxCancel   context.CancelFunc
18
-	connMock    *testlib.NetConnMock
19
-	tickChannel chan struct{}
20
-	buf         []byte
21
-	c           conn
22
-}
23
-
24
-func (suite *ConnTestSuite) SetupTest() {
25
-	ctx, cancel := context.WithCancel(context.Background())
26
-
27
-	suite.tickChannel = make(chan struct{}, 1)
28
-	suite.connMock = &testlib.NetConnMock{}
29
-	suite.ctxCancel = cancel
30
-	suite.buf = make([]byte, 5)
31
-
32
-	suite.c = conn{
33
-		ReadWriteCloser: suite.connMock,
34
-		ctx:             ctx,
35
-		tickChannel:     suite.tickChannel,
36
-	}
37
-}
38
-
39
-func (suite *ConnTestSuite) TestReadOk() {
40
-	suite.connMock.On("Read", mock.Anything).Once().Return(len(suite.buf), nil)
41
-
42
-	n, err := suite.c.Read(suite.buf)
43
-	suite.NoError(err)
44
-	suite.Equal(len(suite.buf), n)
45
-
46
-	select {
47
-	case <-suite.tickChannel:
48
-	default:
49
-		suite.FailNow("cannot find a tick event")
50
-	}
51
-}
52
-
53
-func (suite *ConnTestSuite) TestReadErr() {
54
-	suite.connMock.On("Read", mock.Anything).Once().Return(0, io.EOF)
55
-
56
-	_, err := suite.c.Read(suite.buf)
57
-	suite.True(errors.Is(err, io.EOF))
58
-
59
-	select {
60
-	case <-suite.tickChannel:
61
-	default:
62
-		suite.FailNow("cannot find a tick event")
63
-	}
64
-}
65
-
66
-func (suite *ConnTestSuite) TestReadContextDone() {
67
-	suite.connMock.On("Read", mock.Anything).Once().Return(len(suite.buf), nil)
68
-	suite.ctxCancel()
69
-
70
-	suite.tickChannel <- struct{}{}
71
-
72
-	suite.c.Read(suite.buf) // nolint: errcheck
73
-}
74
-
75
-func (suite *ConnTestSuite) TestWriteOk() {
76
-	suite.connMock.On("Write", mock.Anything).Once().Return(len(suite.buf), nil)
77
-
78
-	n, err := suite.c.Write(suite.buf)
79
-	suite.NoError(err)
80
-	suite.Equal(len(suite.buf), n)
81
-
82
-	select {
83
-	case <-suite.tickChannel:
84
-	default:
85
-		suite.FailNow("cannot find a tick event")
86
-	}
87
-}
88
-
89
-func (suite *ConnTestSuite) TestWriteErr() {
90
-	suite.connMock.On("Write", mock.Anything).Once().Return(0, io.EOF)
91
-
92
-	_, err := suite.c.Write(suite.buf)
93
-	suite.True(errors.Is(err, io.EOF))
94
-
95
-	select {
96
-	case <-suite.tickChannel:
97
-	default:
98
-		suite.FailNow("cannot find a tick event")
99
-	}
100
-}
101
-
102
-func (suite *ConnTestSuite) TestWriteContextDone() {
103
-	suite.connMock.On("Write", mock.Anything).Once().Return(len(suite.buf), nil)
104
-	suite.ctxCancel()
105
-
106
-	suite.tickChannel <- struct{}{}
107
-
108
-	suite.c.Write(suite.buf) // nolint: errcheck
109
-}
110
-
111
-func (suite *ConnTestSuite) TearDownTest() {
112
-	select {
113
-	case <-suite.tickChannel:
114
-	default:
115
-	}
116
-
117
-	close(suite.tickChannel)
118
-
119
-	suite.connMock.AssertExpectations(suite.T())
120
-}
121
-
122
-func TestConn(t *testing.T) {
123
-	t.Parallel()
124
-	suite.Run(t, &ConnTestSuite{})
125
-}

+ 9
- 0
mtglib/internal/relay/init.go Dosyayı Görüntüle

@@ -1,5 +1,14 @@
1 1
 package relay
2 2
 
3
+import "time"
4
+
5
+const (
6
+	ConnectionTimeToLiveMin = 2 * time.Minute
7
+	ConnectionTimeToLiveMax = 10 * time.Minute
8
+	TimeoutMin              = 20 * time.Second
9
+	TimeoutMax              = time.Minute
10
+)
11
+
3 12
 type Logger interface {
4 13
 	Printf(msg string, args ...interface{})
5 14
 }

+ 0
- 44
mtglib/internal/relay/init_test.go Dosyayı Görüntüle

@@ -1,49 +1,5 @@
1 1
 package relay_test
2 2
 
3
-import (
4
-	"bytes"
5
-	"io"
6
-	"sync"
7
-)
8
-
9 3
 type loggerMock struct{}
10 4
 
11 5
 func (l loggerMock) Printf(format string, args ...interface{}) {}
12
-
13
-type rwcMock struct {
14
-	bytes.Buffer
15
-
16
-	closed bool
17
-	mutex  sync.Mutex
18
-}
19
-
20
-func (r *rwcMock) Read(p []byte) (int, error) {
21
-	r.mutex.Lock()
22
-	defer r.mutex.Unlock()
23
-
24
-	if r.closed {
25
-		return 0, io.EOF
26
-	}
27
-
28
-	return r.Buffer.Read(p) // nolint: wrapcheck
29
-}
30
-
31
-func (r *rwcMock) Write(p []byte) (int, error) {
32
-	r.mutex.Lock()
33
-	defer r.mutex.Unlock()
34
-
35
-	if r.closed {
36
-		return 0, io.EOF
37
-	}
38
-
39
-	return r.Buffer.Write(p) // nolint: wrapcheck
40
-}
41
-
42
-func (r *rwcMock) Close() error {
43
-	r.mutex.Lock()
44
-	defer r.mutex.Unlock()
45
-
46
-	r.closed = true
47
-
48
-	return nil
49
-}

+ 17
- 30
mtglib/internal/relay/pools.go Dosyayı Görüntüle

@@ -1,45 +1,32 @@
1 1
 package relay
2 2
 
3
-import (
4
-	"context"
5
-	"sync"
6
-	"time"
7
-)
3
+import "sync"
8 4
 
9
-var relayPool = sync.Pool{
5
+type eastWest struct {
6
+	east []byte
7
+	west []byte
8
+}
9
+
10
+var eastWestPool = sync.Pool{
10 11
 	New: func() interface{} {
11
-		return &Relay{
12
-			tickChannel:  make(chan struct{}),
13
-			errorChannel: make(chan error, 1),
14
-		}
12
+		return &eastWest{}
15 13
 	},
16 14
 }
17 15
 
18
-func AcquireRelay(ctx context.Context, logger Logger, bufferSize int, idleTimeout time.Duration) *Relay {
19
-	ctx, cancel := context.WithCancel(ctx)
20
-
21
-	r, ok := relayPool.Get().(*Relay)
22
-	if !ok {
23
-		panic("Relay pool has no relay!")
24
-	}
25
-
26
-	r.ctx = ctx
27
-	r.ctxCancel = cancel
28
-	r.logger = logger
29
-	r.tickTimeout = idleTimeout
16
+func acquireEastWest(bufferSize int) *eastWest {
17
+	wanted := eastWestPool.Get().(*eastWest) // nolint: forcetypeassert
30 18
 
31
-	if len(r.eastBuffer) != bufferSize {
32
-		r.eastBuffer = make([]byte, bufferSize)
19
+	if len(wanted.east) != bufferSize {
20
+		wanted.east = make([]byte, bufferSize)
33 21
 	}
34 22
 
35
-	if len(r.westBuffer) != bufferSize {
36
-		r.westBuffer = make([]byte, bufferSize)
23
+	if len(wanted.west) != bufferSize {
24
+		wanted.west = make([]byte, bufferSize)
37 25
 	}
38 26
 
39
-	return r
27
+	return wanted
40 28
 }
41 29
 
42
-func ReleaseRelay(r *Relay) {
43
-	r.Reset()
44
-	relayPool.Put(r)
30
+func releaseEastWest(ew *eastWest) {
31
+	eastWestPool.Put(ew)
45 32
 }

+ 25
- 104
mtglib/internal/relay/relay.go Dosyayı Görüntüle

@@ -3,127 +3,48 @@ package relay
3 3
 import (
4 4
 	"context"
5 5
 	"io"
6
+	"net"
6 7
 	"sync"
7
-	"time"
8 8
 )
9 9
 
10
-type Relay struct {
11
-	ctx          context.Context
12
-	ctxCancel    context.CancelFunc
13
-	logger       Logger
14
-	processMutex sync.Mutex
15
-	eastBuffer   []byte
16
-	westBuffer   []byte
17
-	tickChannel  chan struct{}
18
-	errorChannel chan error
19
-	tickTimeout  time.Duration
20
-}
21
-
22
-func (r *Relay) Reset() {
23
-	r.processMutex.Lock()
24
-	defer r.processMutex.Unlock()
10
+func Relay(ctx context.Context, log Logger, bufferSize int,
11
+	telegramConn net.Conn, clientConn io.ReadWriteCloser) {
12
+	defer telegramConn.Close()
13
+	defer clientConn.Close()
25 14
 
26
-	if r.ctxCancel != nil {
27
-		r.ctxCancel()
28
-	}
15
+	ctx, cancel := context.WithTimeout(ctx, getConnectionTimeToLive())
16
+	defer cancel()
29 17
 
30
-	r.ctx = nil
31
-	r.ctxCancel = nil
32
-	r.logger = nil
33
-}
18
+	go func() {
19
+		<-ctx.Done()
20
+		telegramConn.Close()
21
+		clientConn.Close()
22
+	}()
34 23
 
35
-func (r *Relay) Process(eastConn, westConn io.ReadWriteCloser) error {
36
-	r.processMutex.Lock()
37
-	defer r.processMutex.Unlock()
24
+	buffers := acquireEastWest(bufferSize)
25
+	defer releaseEastWest(buffers)
38 26
 
39
-	eastConn = conn{
40
-		ReadWriteCloser: eastConn,
41
-		ctx:             r.ctx,
42
-		tickChannel:     r.tickChannel,
43
-	}
44
-	westConn = conn{
45
-		ReadWriteCloser: westConn,
46
-		ctx:             r.ctx,
47
-		tickChannel:     r.tickChannel,
27
+	telegramConn = conn{
28
+		Conn: telegramConn,
48 29
 	}
49 30
 
50 31
 	wg := &sync.WaitGroup{}
51
-	wg.Add(3) // nolint: gomnd
52
-
53
-	go r.runObserver(eastConn, westConn, wg)
32
+	wg.Add(2) // nolint: gomnd
54 33
 
55
-	go r.transmit(eastConn, westConn, r.westBuffer, "west", wg)
34
+	go pump(log, telegramConn, clientConn, wg, buffers.east, "east -> west")
56 35
 
57
-	r.transmit(westConn, eastConn, r.eastBuffer, "east", wg)
36
+	pump(log, clientConn, telegramConn, wg, buffers.west, "west -> east")
58 37
 
59 38
 	wg.Wait()
60
-
61
-	select {
62
-	case err := <-r.errorChannel:
63
-		return err
64
-	default:
65
-		return nil
66
-	}
67 39
 }
68 40
 
69
-func (r *Relay) transmit(src io.ReadCloser, dst io.WriteCloser,
70
-	buffer []byte, direction string, wg *sync.WaitGroup) {
41
+func pump(log Logger, src io.ReadCloser, dst io.WriteCloser, wg *sync.WaitGroup,
42
+	buf []byte, direction string) {
71 43
 	defer wg.Done()
44
+	defer src.Close()
45
+	defer dst.Close()
72 46
 
73
-	defer func() {
74
-		r.ctxCancel()
75
-		src.Close()
76
-		dst.Close()
77
-	}()
78
-
79
-	if _, err := io.CopyBuffer(dst, src, buffer); err != nil {
80
-		r.logger.Printf("error '%v' happened on direction %s", err, direction)
81
-
82
-		select {
83
-		case <-r.ctx.Done():
84
-			err = r.ctx.Err()
85
-		default:
86
-		}
87
-
88
-		select {
89
-		case r.errorChannel <- err:
90
-		default:
91
-		}
92
-	}
93
-}
94
-
95
-func (r *Relay) runObserver(one, another io.Closer, wg *sync.WaitGroup) {
96
-	defer wg.Done()
97
-
98
-	ticker := time.NewTicker(time.Second)
99
-
100
-	defer func() {
101
-		one.Close()
102
-		another.Close()
103
-
104
-		ticker.Stop()
105
-
106
-		select {
107
-		case <-ticker.C:
108
-		default:
109
-		}
110
-	}()
111
-
112
-	lastTickAt := time.Now()
113
-
114
-	for {
115
-		select {
116
-		case <-r.ctx.Done():
117
-			return
118
-		case <-r.tickChannel:
119
-			lastTickAt = time.Now()
120
-		case <-ticker.C:
121
-			if time.Since(lastTickAt) > r.tickTimeout {
122
-				r.logger.Printf("exit due to a timeout")
123
-				r.ctxCancel()
124
-
125
-				return
126
-			}
127
-		}
47
+	if n, err := io.CopyBuffer(dst, src, buf); err != nil {
48
+		log.Printf("cannot pump %s (written %d bytes): %w", direction, n, err)
128 49
 	}
129 50
 }

+ 23
- 44
mtglib/internal/relay/relay_test.go Dosyayı Görüntüle

@@ -4,7 +4,6 @@ import (
4 4
 	"context"
5 5
 	"io"
6 6
 	"testing"
7
-	"time"
8 7
 
9 8
 	"github.com/9seconds/mtg/v2/internal/testlib"
10 9
 	"github.com/9seconds/mtg/v2/mtglib/internal/relay"
@@ -15,60 +14,40 @@ import (
15 14
 type RelayTestSuite struct {
16 15
 	suite.Suite
17 16
 
18
-	ctx       context.Context
19
-	ctxCancel context.CancelFunc
20
-	r         *relay.Relay
17
+	loggerMock       relay.Logger
18
+	ctx              context.Context
19
+	ctxCancel        context.CancelFunc
20
+	telegramConnMock *testlib.NetConnMock
21
+	clientConnMock   *testlib.NetConnMock
21 22
 }
22 23
 
23 24
 func (suite *RelayTestSuite) SetupTest() {
24
-	suite.ctx, suite.ctxCancel = context.WithCancel(context.Background())
25
-	suite.r = relay.AcquireRelay(suite.ctx, loggerMock{}, 4096, time.Second)
25
+	ctx, cancel := context.WithCancel(context.Background())
26
+	suite.ctx = ctx
27
+	suite.ctxCancel = cancel
28
+	suite.loggerMock = &loggerMock{}
29
+	suite.telegramConnMock = &testlib.NetConnMock{}
30
+	suite.clientConnMock = &testlib.NetConnMock{}
26 31
 }
27 32
 
28 33
 func (suite *RelayTestSuite) TearDownTest() {
29 34
 	suite.ctxCancel()
30
-	relay.ReleaseRelay(suite.r)
31
-	suite.r = nil
35
+	suite.telegramConnMock.AssertExpectations(suite.T())
36
+	suite.clientConnMock.AssertExpectations(suite.T())
32 37
 }
33 38
 
34
-func (suite *RelayTestSuite) TestCancelled() {
35
-	suite.ctxCancel()
36
-
37
-	eastConn := &rwcMock{}
38
-	eastConn.Write([]byte{1, 2, 3, 4, 5}) // nolint: errcheck
39
-
40
-	westConn := &rwcMock{}
41
-	westConn.Write([]byte{100, 101, 102}) // nolint: errcheck
42
-
43
-	suite.Nil(suite.r.Process(eastConn, westConn))
44
-}
45
-
46
-func (suite *RelayTestSuite) TestCopyFine() {
47
-	eastConn := &rwcMock{}
48
-	eastConn.Write([]byte{1, 2, 3, 4, 5}) // nolint: errcheck
49
-
50
-	westConn := &rwcMock{}
51
-	westConn.Write([]byte{100, 101, 102}) // nolint: errcheck
52
-
53
-	// yes, this test is not good enough. but apparently, if it hangs,
54
-	// we can debug most of possible issues.
55
-	_ = suite.r.Process(eastConn, westConn)
56
-}
57
-
58
-func (suite *RelayTestSuite) TestTimeout() {
59
-	eastConn := &rwcMock{}
60
-	eastConn.Write([]byte{1, 2, 3, 4, 5}) // nolint: errcheck
39
+func (suite *RelayTestSuite) TestExit() {
40
+	suite.telegramConnMock.On("SetReadDeadline", mock.Anything).Return(nil)
41
+	suite.telegramConnMock.On("Close").Return(nil)
42
+	suite.telegramConnMock.On("Read", mock.Anything).Return(10, io.EOF).Once()
43
+	suite.telegramConnMock.On("Write", mock.Anything).Return(10, io.EOF).Maybe()
61 44
 
62
-	westConn := &testlib.NetConnMock{}
63
-	westConn.On("Close").Return(nil)
64
-	westConn.On("Read", mock.Anything).Return(0, io.EOF).Run(func(_ mock.Arguments) {
65
-		time.Sleep(2 * time.Second)
66
-	})
67
-	westConn.On("Write", mock.Anything).Return(0, io.EOF).Run(func(_ mock.Arguments) {
68
-		time.Sleep(2 * time.Second)
69
-	})
45
+	suite.clientConnMock.On("Read", mock.Anything).Return(0, io.EOF).Once()
46
+	suite.clientConnMock.On("Write", mock.Anything).Return(10, io.EOF).Maybe()
47
+	suite.clientConnMock.On("Close").Return(nil)
70 48
 
71
-	suite.Error(suite.r.Process(eastConn, westConn))
49
+	relay.Relay(suite.ctx, suite.loggerMock, 1024,
50
+		suite.telegramConnMock, suite.clientConnMock)
72 51
 }
73 52
 
74 53
 func TestRelay(t *testing.T) {

+ 22
- 0
mtglib/internal/relay/timeouts.go Dosyayı Görüntüle

@@ -0,0 +1,22 @@
1
+package relay
2
+
3
+import (
4
+	"math/rand"
5
+	"time"
6
+)
7
+
8
+func getConnectionTimeToLive() time.Duration {
9
+	return getTime(ConnectionTimeToLiveMin, ConnectionTimeToLiveMax)
10
+}
11
+
12
+func getTimeout() time.Duration {
13
+	return getTime(TimeoutMin, TimeoutMax)
14
+}
15
+
16
+func getTime(minDuration, maxDuration time.Duration) time.Duration {
17
+	minDurationInSeconds := int(minDuration.Seconds())
18
+	maxDurationInSeconds := int(maxDuration.Seconds())
19
+	number := minDurationInSeconds + rand.Intn(maxDurationInSeconds-minDurationInSeconds)
20
+
21
+	return time.Duration(number) * time.Second
22
+}

+ 37
- 0
mtglib/internal/relay/timeouts_internal_test.go Dosyayı Görüntüle

@@ -0,0 +1,37 @@
1
+package relay
2
+
3
+import (
4
+	"fmt"
5
+	"testing"
6
+
7
+	"github.com/stretchr/testify/suite"
8
+)
9
+
10
+type TimeoutsTestSuite struct {
11
+	suite.Suite
12
+}
13
+
14
+func (suite *TimeoutsTestSuite) TestGetConnectionTimeToLive() {
15
+	for i := 0; i < 100; i++ {
16
+		value := getConnectionTimeToLive()
17
+		message := fmt.Sprintf("generated value is %v", value)
18
+
19
+		suite.GreaterOrEqual(value, ConnectionTimeToLiveMin, message)
20
+		suite.LessOrEqual(value, ConnectionTimeToLiveMax, message)
21
+	}
22
+}
23
+
24
+func (suite *TimeoutsTestSuite) TestGetTimeout() {
25
+	for i := 0; i < 100; i++ {
26
+		value := getTimeout()
27
+		message := fmt.Sprintf("generated value is %v", value)
28
+
29
+		suite.GreaterOrEqual(value, TimeoutMin, message)
30
+		suite.LessOrEqual(value, TimeoutMax, message)
31
+	}
32
+}
33
+
34
+func TestTimeouts(t *testing.T) {
35
+	t.Parallel()
36
+	suite.Run(t, &TimeoutsTestSuite{})
37
+}

+ 14
- 16
mtglib/proxy.go Dosyayı Görüntüle

@@ -23,7 +23,6 @@ type Proxy struct {
23 23
 	ctxCancel       context.CancelFunc
24 24
 	streamWaitGroup sync.WaitGroup
25 25
 
26
-	idleTimeout          time.Duration
27 26
 	tolerateTimeSkewness time.Duration
28 27
 	bufferSize           int
29 28
 	domainFrontingPort   int
@@ -81,13 +80,13 @@ func (p *Proxy) ServeConn(conn net.Conn) {
81 80
 		return
82 81
 	}
83 82
 
84
-	rel := relay.AcquireRelay(ctx,
85
-		p.logger.Named("relay"), p.bufferSize, p.idleTimeout)
86
-	defer relay.ReleaseRelay(rel)
87
-
88
-	if err := rel.Process(ctx.clientConn, ctx.telegramConn); err != nil {
89
-		p.logger.DebugError("relay has been finished", err)
90
-	}
83
+	relay.Relay(
84
+		ctx,
85
+		ctx.logger.Named("relay"),
86
+		p.bufferSize,
87
+		ctx.telegramConn,
88
+		ctx.clientConn,
89
+	)
91 90
 }
92 91
 
93 92
 // Serve starts a proxy on a given listener.
@@ -255,13 +254,13 @@ func (p *Proxy) doDomainFronting(ctx *streamContext, conn *connRewind) {
255 254
 		stream:   p.eventStream,
256 255
 	}
257 256
 
258
-	rel := relay.AcquireRelay(ctx,
259
-		p.logger.Named("domain-fronting"), p.bufferSize, p.idleTimeout)
260
-	defer relay.ReleaseRelay(rel)
261
-
262
-	if err := rel.Process(conn, frontConn); err != nil {
263
-		p.logger.DebugError("domain fronting relay has been finished", err)
264
-	}
257
+	relay.Relay(
258
+		ctx,
259
+		ctx.logger.Named("domain-fronting"),
260
+		p.bufferSize,
261
+		frontConn,
262
+		conn,
263
+	)
265 264
 }
266 265
 
267 266
 // NewProxy makes a new proxy instance.
@@ -287,7 +286,6 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) {
287 286
 		logger:               opts.getLogger("proxy"),
288 287
 		domainFrontingPort:   opts.getDomainFrontingPort(),
289 288
 		tolerateTimeSkewness: opts.getTolerateTimeSkewness(),
290
-		idleTimeout:          opts.getIdleTimeout(),
291 289
 		bufferSize:           opts.getBufferSize(),
292 290
 		telegram:             tg,
293 291
 	}

+ 0
- 8
mtglib/proxy_opts.go Dosyayı Görüntüle

@@ -143,14 +143,6 @@ func (p ProxyOpts) getDomainFrontingPort() int {
143 143
 	return int(p.DomainFrontingPort)
144 144
 }
145 145
 
146
-func (p ProxyOpts) getIdleTimeout() time.Duration {
147
-	if p.IdleTimeout == 0 {
148
-		return DefaultIdleTimeout
149
-	}
150
-
151
-	return p.IdleTimeout
152
-}
153
-
154 146
 func (p ProxyOpts) getTolerateTimeSkewness() time.Duration {
155 147
 	if p.TolerateTimeSkewness == 0 {
156 148
 		return DefaultTolerateTimeSkewness

+ 4
- 29
network/default.go Dosyayı Görüntüle

@@ -5,8 +5,6 @@ import (
5 5
 	"fmt"
6 6
 	"net"
7 7
 	"time"
8
-
9
-	"github.com/libp2p/go-reuseport"
10 8
 )
11 9
 
12 10
 type defaultDialer struct {
@@ -31,36 +29,14 @@ func (d *defaultDialer) DialContext(ctx context.Context, network, address string
31 29
 		return nil, fmt.Errorf("cannot dial to %s: %w", address, err)
32 30
 	}
33 31
 
34
-	tcpConn, ok := conn.(*net.TCPConn)
35
-	if !ok {
36
-		panic("conn type is not tcp")
37
-	}
38
-
39
-	if err := tcpConn.SetNoDelay(true); err != nil {
32
+	// we do not need to call to end user. End users call us.
33
+	if err := SetServerSocketOptions(conn, d.bufferSize); err != nil {
40 34
 		conn.Close()
41 35
 
42
-		return nil, fmt.Errorf("cannot set TCP_NO_DELAY: %w", err)
43
-	}
44
-
45
-	if err := tcpConn.SetReadBuffer(d.bufferSize); err != nil {
46
-		tcpConn.Close()
47
-
48
-		return nil, fmt.Errorf("cannot set read buffer size: %w", err)
49
-	}
50
-
51
-	if err := tcpConn.SetWriteBuffer(d.bufferSize); err != nil {
52
-		tcpConn.Close()
53
-
54
-		return nil, fmt.Errorf("cannot set write buffer size: %w", err)
55
-	}
56
-
57
-	if err := tcpConn.SetKeepAlive(true); err != nil {
58
-		tcpConn.Close()
59
-
60
-		return nil, fmt.Errorf("cannot enable keep-alive: %w", err)
36
+		return nil, fmt.Errorf("cannot set socket options: %w", err)
61 37
 	}
62 38
 
63
-	return tcpConn, nil
39
+	return conn, nil
64 40
 }
65 41
 
66 42
 // NewDefaultDialer build a new dialer which dials bypassing proxies
@@ -87,7 +63,6 @@ func NewDefaultDialer(timeout time.Duration, bufferSize int) (Dialer, error) {
87 63
 	return &defaultDialer{
88 64
 		Dialer: net.Dialer{
89 65
 			Timeout: timeout,
90
-			Control: reuseport.Control,
91 66
 		},
92 67
 		bufferSize: bufferSize,
93 68
 	}, nil

+ 4
- 0
network/init.go Dosyayı Görüntüle

@@ -70,6 +70,10 @@ const (
70 70
 
71 71
 	// DNSTimeout defines a timeout for DNS queries.
72 72
 	DNSTimeout = 5 * time.Second
73
+
74
+	// tcpLingerTimeout defines a number of seconds to wait for sending
75
+	// unacknowledged data.
76
+	tcpLingerTimeout = 1
73 77
 )
74 78
 
75 79
 var (

+ 71
- 0
network/sockopts.go Dosyayı Görüntüle

@@ -0,0 +1,71 @@
1
+package network
2
+
3
+import (
4
+	"fmt"
5
+	"net"
6
+
7
+	"golang.org/x/sys/unix"
8
+)
9
+
10
+// SetClientSocketOptions tunes a TCP socket that represents a connection to
11
+// end user (not Telegram service or fronting domain).
12
+func SetClientSocketOptions(conn net.Conn, bufferSize int) error {
13
+	tcpConn := conn.(*net.TCPConn) // nolint: forcetypeassert
14
+
15
+	if err := tcpConn.SetNoDelay(false); err != nil {
16
+		return fmt.Errorf("cannot disable TCP_NO_DELAY: %w", err)
17
+	}
18
+
19
+	return setCommonSocketOptions(tcpConn, bufferSize)
20
+}
21
+
22
+// SetServerSocketOptions tunes a TCP socket that represents a connection to
23
+// remote server like Telegram or fronting domain (but not end user).
24
+func SetServerSocketOptions(conn net.Conn, bufferSize int) error {
25
+	tcpConn := conn.(*net.TCPConn) // nolint: forcetypeassert
26
+
27
+	if err := tcpConn.SetNoDelay(true); err != nil {
28
+		return fmt.Errorf("cannot enable TCP_NO_DELAY: %w", err)
29
+	}
30
+
31
+	return setCommonSocketOptions(tcpConn, bufferSize)
32
+}
33
+
34
+func setCommonSocketOptions(conn *net.TCPConn, bufferSize int) error {
35
+	if err := conn.SetReadBuffer(bufferSize); err != nil {
36
+		return fmt.Errorf("cannot set read buffer size: %w", err)
37
+	}
38
+
39
+	if err := conn.SetWriteBuffer(bufferSize); err != nil {
40
+		return fmt.Errorf("cannot set write buffer size: %w", err)
41
+	}
42
+
43
+	if err := conn.SetKeepAlive(false); err != nil {
44
+		return fmt.Errorf("cannot disable TCP keepalive probes: %w", err)
45
+	}
46
+
47
+	if err := conn.SetLinger(tcpLingerTimeout); err != nil {
48
+		return fmt.Errorf("cannot set TCP linger timeout: %w", err)
49
+	}
50
+
51
+	rawConn, err := conn.SyscallConn()
52
+	if err != nil {
53
+		return fmt.Errorf("cannot get underlying raw connection")
54
+	}
55
+
56
+	rawConn.Control(func(fd uintptr) { // nolint: errcheck
57
+		err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
58
+		if err != nil {
59
+			err = fmt.Errorf("cannot set SO_REUSEADDR: %w", err)
60
+
61
+			return
62
+		}
63
+
64
+		err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
65
+		if err != nil {
66
+			err = fmt.Errorf("cannot set SO_REUSEPORT: %w", err)
67
+		}
68
+	})
69
+
70
+	return nil
71
+}

Loading…
İptal
Kaydet