REPOSITORY / ScuroNeko/mtg

Compare commits

DIFF REPOSITORY

Compare commits

...
55 Commits
Author SHA1 Message Date
Sergey ArkhipovandGitHub 9d67414db6 Merge pull request #264 from 9seconds/goreleaser-v1
Use goreleaser for v1
2022-03-21 14:32:11 +03:00
9seconds a587f85dd2 Use goreleaser for v1 2022-03-21 14:30:06 +03:00
9seconds 18a52340fa Update dependencies 2022-03-21 12:44:03 +03:00
9seconds 981ffb0dbe Update update-deps target 2022-03-21 12:43:29 +03:00
Sergey ArkhipovandGitHub b976e74fc0 Merge pull request #260 from 9seconds/go118-v1
Support of Go 1.18 for v1
2022-03-19 15:10:20 +03:00
9seconds b2de98c8f9 Update docker build timeout 2022-03-19 14:52:41 +03:00
9seconds 6f3abf0990 Update dockerfile 2022-03-19 14:36:17 +03:00
9seconds e74726af70 Updates for go 1.18 2022-03-19 14:36:04 +03:00
9seconds 8da55410de Run gofumpt 2022-03-19 14:12:14 +03:00
9seconds 4b1f823777 Update dependencies 2021-08-30 14:49:23 +03:00
Sergey ArkhipovandGitHub 511090b806 Merge pull request #205 from 9seconds/golang-1.17-v1
[v1] Upgrade to golang 1.17
2021-08-30 11:54:33 +03:00
Sergey ArkhipovandGitHub eba378817e Merge pull request #204 from 9seconds/golangcilint-1.42-v1
[v1] Upgrade golangci-lint for 1.42
2021-08-30 11:54:03 +03:00
9seconds c178b4b9cc Upgrade to golang 1.17 2021-08-30 11:51:11 +03:00
9seconds 3e0880f6b4 Upgrade golangci-lint for 1.42 2021-08-30 11:46:32 +03:00
Sergey ArkhipovandGitHub 7718f62477 Merge pull request #179 from 9seconds/golang1.16
Update dockerfile to golang 1.16
2021-03-03 17:54:13 +03:00
9seconds df0994dad3 Update dockerfile to golang 1.16 2021-03-03 17:43:38 +03:00
Sergey ArkhipovandGitHub dca43853fb Merge pull request #178 from 9seconds/ci-arm32
Build for arm 32 platforms
2021-03-03 17:42:59 +03:00
9seconds ea8e31346c Build for arm 32 platforms 2021-03-03 17:30:47 +03:00
Sergey ArkhipovandGitHub ed495b3800 Merge pull request #177 from 9seconds/faketls-hotfix
Correct rewinding for faketls
2021-03-03 17:24:38 +03:00
9seconds 4025f223c4 Correct rewinding for faketls 2021-03-03 17:18:16 +03:00
9seconds 90e0ce4c48 Update dependencies 2021-02-26 08:22:01 +03:00
Sergey ArkhipovandGitHub ac0b442b43 Merge pull request #176 from 9seconds/fix-urls
Fix urls for missed IPs
2021-03-03 15:40:15 +03:00
9seconds af7021fac8 Fix urls for missed IPs 2021-02-26 08:11:34 +03:00
9seconds 5468625212 Use CI on supported branches 2021-02-26 08:04:22 +03:00
9seconds 345c1bf715 Update ignores 2021-02-26 04:41:08 +03:00
Sergey ArkhipovandGitHub 52d47a9786 Create codeql-analysis.yml 2021-03-02 22:01:47 +03:00
Sergey ArkhipovandGitHub 2ba79a8508 Create SECURITY.md 2021-03-02 22:00:18 +03:00
Sergey ArkhipovandGitHub ce7769472d Merge pull request #175 from 9seconds/ci
Integrate with Github actions
2021-03-02 21:43:20 +03:00
Sergey ArkhipovandGitHub eb5eea2625 Merge pull request #174 from 9seconds/linter
Update golangci-linter
2021-03-02 16:18:05 +03:00
Sergey ArkhipovandGitHub d965dc3c07 Merge pull request #173 from 9seconds/simplify-makefile
Simplify Makefile
2021-03-02 15:52:29 +03:00
9seconds 040b3c371c Add github workflow 2021-02-26 04:12:00 +03:00
9seconds c7ba8e54be Remove travis 2021-02-26 03:58:48 +03:00
9seconds 33b1a5426c Update golangci-linter 2021-02-26 00:52:09 +03:00
9seconds 91197c0334 Simplify Makefile
This commit removes GO111MODULE and simplifies internal structure
2021-02-26 00:25:16 +03:00
Sergey ArkhipovandGitHub e075169dd4 Merge pull request #166 from biozz/fix-statsd-docs
Fix docs related to statsd usage
2021-01-06 08:08:02 +03:00
Ivan Elfimov 225444b1b3 Update README.md
- remove MTG_STATSD_PORT, because it is not used in the code
- update MTG_STATSD_ADDR description to reflect all possible use cases
2021-01-02 21:21:23 +03:00
Sergey ArkhipovandGitHub 586ac9dcb9 Merge pull request #160 from a68366/master
Fix t.me QR code. Closes #159
2020-10-19 10:56:39 +03:00
a68366andGitHub c3be5311e8 Fix t.me QR code. Closes #159 2020-10-08 19:32:36 +03:00
9seconds bfeded67ee Update travis 2020-09-21 11:46:13 +03:00
9seconds dde0d25b77 Update golangci lint to 1.31.0 2020-09-21 11:45:09 +03:00
9seconds 296a34cd6e Update dockerfile to use 1.15 2020-09-21 11:44:06 +03:00
9seconds 44cea68e83 Upgrade dependencies 2020-09-21 11:43:23 +03:00
Sergey ArkhipovandGitHub 5d17e264e6 Merge pull request #156 from 9seconds/no-pools
Get rid of sync pools
2020-08-10 15:20:15 +03:00
9seconds 7ef1e99f66 Add 1.14 to a travis 2020-08-10 15:02:05 +03:00
9seconds 3acbacbdb3 Install lint in a local directory 2020-08-10 15:01:38 +03:00
9seconds 5fd7062972 Update dependencies 2020-08-10 14:41:22 +03:00
9seconds 7a6695f6c4 Update golangci-lint 2020-08-10 14:39:50 +03:00
9seconds 8ac786581b Update golangci lint 2020-08-10 13:30:07 +03:00
9seconds 86a8f69273 Cleanup pools from wrappes 2020-08-10 13:29:08 +03:00
9seconds 95b16cd805 Cleanup pools from tlstypes 2020-08-10 13:27:23 +03:00
9seconds 3996b9a6b8 Remove pools from faketls 2020-08-10 13:21:30 +03:00
Sergey ArkhipovandGitHub e286dea650 Merge pull request #151 from FollowMeDown/master
Fix Keep-Alive Issue for OpenBSD/ArchLinux
2020-08-10 12:49:16 +03:00
DEFACE 5e27e48129 Fix Keep-Alive Issue for OpenBSD/ArchLinux 2020-06-15 21:38:35 +02:00
Sergey ArkhipovandGitHub 95abb54dc8 Merge pull request #146 from 9seconds/fix-docker-image
Updates for dockerfile
2020-05-19 11:31:25 +03:00
9seconds dbd3d3c266 Updates for dockerfile 2020-05-19 11:26:08 +03:00
84 changed files with 1165 additions and 677 deletions
+7 -1
View File
@@ -1,3 +1,9 @@
version.go
vendor/ vendor/
tags tags
.github/
.bin/
*.md
mtg
.golangci.toml
.gitignore
run.sh
+131
View File
@@ -0,0 +1,131 @@
---
name: CI
on:
push:
tags:
- v*
branches:
- master
- stable
- v1
release:
types:
- published
- released
pull_request:
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
jobs:
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
go_version:
- ^1.18
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go_version }}
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: Run tests
run: go test -coverprofile=./coverage.txt -covermode=atomic -v ./...
- name: Collect coverage
uses: codecov/codecov-action@v1
with:
file: ./coverage.txt
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Run linter
uses: golangci/golangci-lint-action@v2
with:
version: v1.45.0
docker:
name: Docker
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Get Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: nineseconds/mtg,ghcr.io/9seconds/mtg
tag-semver: "{{version}},{{major}},{{major}}.{{minor}}"
- name: Setup QEMU
uses: docker/setup-qemu-action@v1
- name: Setup BuildX
uses: docker/setup-buildx-action@v1
- name: Setup cache
uses: actions/cache@v2
with:
path: /tmp/buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to GHCR.io
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_PAT }}
- name: Build and push
uses: docker/build-push-action@v2
with:
pull: true
context: .
platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/arm/v6
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
cache-from: type=local,src=/tmp/buildx-cache
cache-to: type=local,dest=/tmp/buildx-cache
+69
View File
@@ -0,0 +1,69 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches:
- master
- stable
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '24 20 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+2 -2
View File
@@ -7,5 +7,5 @@
*.out *.out
mtg mtg
vendor/ vendor/
version.go .bin/
ccbuilds/ dist/
+1 -2
View File
@@ -3,11 +3,10 @@ concurrency = 4
deadline = "2m" deadline = "2m"
tests = true tests = true
skip-dirs = ["vendor"] skip-dirs = ["vendor"]
skip-files = ["version.go"]
[output] [output]
format = "colored-line-number" format = "colored-line-number"
[linters] [linters]
enable-all = true enable-all = true
disable = ["gochecknoglobals", "gomnd"] disable = ["thelper", "ireturn", "varnamelen", "gochecknoglobals", "gas", "goerr113", "exhaustivestruct", "containedctx"]
+65
View File
@@ -0,0 +1,65 @@
---
project_name: mtg
before:
hooks:
- go mod tidy
- go generate ./...
builds:
- binary: '{{ .ProjectName }}'
goos:
- darwin
- freebsd
- linux
- netbsd
- openbsd
goarch:
- 386
- amd64
- arm
- arm64
goarm:
- 6
- 7
env:
- CGO_ENABLED=0
flags:
- -trimpath
- -mod=readonly
ldflags: -s -w -X main.version={{ .Version }}
ignore:
- goos: darwin
goarch: 386
- goos: freebsd
goarch: arm64
- goos: netbsd
goarch: arm64
- goos: openbsd
goarch: arm64
archives:
- name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
wrap_in_directory: true
format_overrides:
- goos: windows
format: zip
files:
- LICENSE
- README.md
- SECURITY.md
gomod:
proxy: true
snapshot:
name_template: '{{ .Version }}'
checksum:
name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'
source:
enabled: true
name_template: '{{ .ProjectName }}-sources'
-20
View File
@@ -1,20 +0,0 @@
---
language: go
sudo: false
dist: trusty
go:
- 1.13.x
- master
before_script: make prepare
script:
- make all
- make lint
matrix:
allow_failures:
- go: master
- go: 1.14.x # because of golangci-lint
+9 -13
View File
@@ -1,7 +1,7 @@
############################################################################### ###############################################################################
# BUILD STAGE # BUILD STAGE
FROM golang:1.14-alpine FROM golang:1.18-alpine AS build
RUN set -x \ RUN set -x \
&& apk --no-cache --update add \ && apk --no-cache --update add \
@@ -9,15 +9,13 @@ RUN set -x \
ca-certificates \ ca-certificates \
curl \ curl \
git \ git \
make \ make
upx
COPY . /go/src/github.com/9seconds/mtg/ COPY . /app
WORKDIR /app
RUN set -x \ RUN set -x \
&& cd /go/src/github.com/9seconds/mtg \ && make -j 4 static
&& make -j 4 static \
&& upx --ultra-brute -qq ./mtg
############################################################################### ###############################################################################
@@ -26,11 +24,9 @@ RUN set -x \
FROM scratch FROM scratch
ENTRYPOINT ["/mtg"] ENTRYPOINT ["/mtg"]
ENV MTG_IP=0.0.0.0 \ ENV MTG_BIND=0.0.0.0:3128 \
MTG_PORT=3128 \ MTG_STATS_BIND=0.0.0.0:3129
MTG_STATS_IP=0.0.0.0 \
MTG_STATS_PORT=3129
EXPOSE 3128 3129 EXPOSE 3128 3129
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=0 /go/src/github.com/9seconds/mtg/mtg /mtg COPY --from=build /app/mtg /mtg
+63 -44
View File
@@ -2,58 +2,41 @@ ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
IMAGE_NAME := mtg IMAGE_NAME := mtg
APP_NAME := $(IMAGE_NAME) APP_NAME := $(IMAGE_NAME)
CC_BINARIES := $(shell bash -c "echo -n $(APP_NAME)-{linux,freebsd,openbsd}-{386,amd64} $(APP_NAME)-linux-{arm,arm64}") GOLANGCI_LINT_VERSION := v1.45.0
GOLANGCI_LINT_VERSION := v1.24.0
VERSION_GO := $(shell go version) VERSION_GO := $(shell go version)
VERSION_DATE := $(shell date -Ru) VERSION_DATE := $(shell date -Ru)
VERSION_TAG := $(shell git describe --tags --always) VERSION_TAG := $(shell git describe --tags --always)
COMMON_BUILD_FLAGS := -ldflags="-s -w -X 'main.version=$(VERSION_TAG) ($(VERSION_GO)) [$(VERSION_DATE)]'" COMMON_BUILD_FLAGS := -trimpath -mod=readonly -ldflags="-s -w -X 'main.version=$(VERSION_TAG) ($(VERSION_GO)) [$(VERSION_DATE)]'"
MOD_ON := env GO111MODULE=on GOBIN := $(ROOT_DIR)/.bin
MOD_OFF := env GO111MODULE=auto GOTOOL := env "GOBIN=$(GOBIN)" "PATH=$(ROOT_DIR)/.bin:$(PATH)"
# -----------------------------------------------------------------------------
$(APP_NAME):
@$(MOD_ON) go build $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
static-$(APP_NAME):
@$(MOD_ON) env CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
$(APP_NAME)-%: GOOS=$(shell echo -n "$@" | sed 's?$(APP_NAME)-??' | cut -f1 -d-)
$(APP_NAME)-%: GOARCH=$(shell echo -n "$@" | sed 's?$(APP_NAME)-??' | cut -f2 -d-)
$(APP_NAME)-%: ccbuilds
@$(MOD_ON) env "GOOS=$(GOOS)" "GOARCH=$(GOARCH)" \
go build \
$(COMMON_BUILD_FLAGS) \
-o "./ccbuilds/$(APP_NAME)-$(GOOS)-$(GOARCH)"
ccbuilds:
@rm -rf ./ccbuilds && mkdir -p ./ccbuilds
vendor: go.mod go.sum
@$(MOD_ON) go mod vendor
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
.PHONY: all .PHONY: all
all: $(APP_NAME) all: build
.PHONY: build
build:
@go build $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
$(APP_NAME): build
.PHONY: static .PHONY: static
static: static-$(APP_NAME) static:
@env CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo $(COMMON_BUILD_FLAGS) -o "$(APP_NAME)"
.PHONY: crosscompile vendor: go.mod go.sum
crosscompile: $(CC_BINARIES) @$(MOD_ON) go mod vendor
.PHONY: crosscompile-dir .PHONY: test
crosscompile-dir: test:
@rm -rf "$(CC_DIR)" && mkdir -p "$(CC_DIR)" @go test -v ./...
.PHONY: lint .PHONY: citest
lint: vendor citest:
@$(MOD_OFF) golangci-lint run @go test -coverprofile=coverage.txt -covermode=atomic -race -v ./...
.PHONY: clean .PHONY: clean
clean: clean:
@@ -61,14 +44,50 @@ clean:
git reset --hard >/dev/null && \ git reset --hard >/dev/null && \
git submodule foreach --recursive sh -c 'git clean -xfd && git reset --hard' >/dev/null git submodule foreach --recursive sh -c 'git clean -xfd && git reset --hard' >/dev/null
.PHONY: lint
lint:
@$(GOTOOL) golangci-lint run
.PHONY: docker .PHONY: docker
docker: docker:
@docker build --pull -t "$(IMAGE_NAME)" "$(ROOT_DIR)" @docker build --pull -t "$(IMAGE_NAME)" "$(ROOT_DIR)"
.PHONY: prepare .PHONY: doc
prepare: install-lint doc:
@$(GOTOOL) godoc -http 0.0.0.0:10000
.PHONY: install-lint .PHONY: fmt
install-lint: fmt:
@curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \ @$(GOTOOL) gofumpt -w -extra "$(ROOT_DIR)"
| $(MOD_OFF) bash -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION)
.PHONY: release
release:
@$(GOTOOL) goreleaser release --snapshot --rm-dist && \
find "$(ROOT_DIR)/dist" -type d | grep -vP "dist$$" | xargs -r rm -rf && \
rm -f "$(ROOT_DIR)/dist/config.yaml"
.PHONY: install-tools
install-tools: install-tools-lint install-tools-godoc install-tools-gofumpt install-tools-goreleaser
.PHONY: install-tools-lint
install-tools-lint:
@mkdir -p "$(GOBIN)" || true && \
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh \
| bash -s -- -b "$(GOBIN)" "$(GOLANGCI_LINT_VERSION)"
.PHONY: install-tools-godoc
install-tools-godoc:
@mkdir -p "$(GOBIN)" || true && \
$(GOTOOL) go get -u golang.org/x/tools/cmd/godoc
.PHONY: install-tools-gofumpt
install-tools-gofumpt: .bin
@$(GOTOOL) go install mvdan.cc/gofumpt@latest
.PHONY: goreleaser
install-tools-goreleaser: .bin
@$(GOTOOL) go install github.com/goreleaser/goreleaser@latest
.PHONY: update-deps
update-deps:
@go get -u && go mod tidy -go=1.18
+1 -2
View File
@@ -189,8 +189,7 @@ supported environment variables:
| `MTG_IPV6` | `-6`, `--public-ipv6` | [Autodetect](https://ifconfig.co) | IPv6 address:port of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv6 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. | | `MTG_IPV6` | `-6`, `--public-ipv6` | [Autodetect](https://ifconfig.co) | IPv6 address:port of this proxy. This is required if you NAT your proxy or run it in a docker container. In that case, you absolutely need to specify public IPv6 address of the proxy, otherwise either URLs will be broken or proxy could not access Telegram middle proxies. |
| `MTG_STATS_BIND` | `-t`, `--stats-bind` | `127.0.0.1:3129` | Which hist:port should we bind the internal statistics HTTP server (Prometheus). | | `MTG_STATS_BIND` | `-t`, `--stats-bind` | `127.0.0.1:3129` | Which hist:port should we bind the internal statistics HTTP server (Prometheus). |
| `MTG_STATS_NAMESPACE` | `--stats-namespace` | `mtg` | Which namespace should be used for prometheus metrics. | | `MTG_STATS_NAMESPACE` | `--stats-namespace` | `mtg` | Which namespace should be used for prometheus metrics. |
| `MTG_STATSD_ADDR` | `--statsd-addr` | | IP:host addresses of statsd service. No defaults, by defaults we do not send anything there. | | `MTG_STATSD_ADDR` | `--statsd-addr` | | host:port of statsd service. No defaults, by default we do not send anything there. |
| `MTG_STATSD_PORT` | `--statsd-port` | `8125` | Which port should we use to work with statsd. |
| `MTG_STATSD_PREFIX` | `--statsd-prefix` | `mtg` | Which bucket prefix we should use. For example, if you set `mtg`, then metric `traffic.ingress` would be send as `mtg.traffic.ingress`. | | `MTG_STATSD_PREFIX` | `--statsd-prefix` | `mtg` | Which bucket prefix we should use. For example, if you set `mtg`, then metric `traffic.ingress` would be send as `mtg.traffic.ingress`. |
| `MTG_STATSD_TAGS_FORMAT` | `--statsd-tags-format` | | Which tags format we should use. By default, we are using default vanilla statsd tags format but if you want to send directly to InfluxDB or Datadog, please specify it there. Possible options are `influxdb` and `datadog`. | | `MTG_STATSD_TAGS_FORMAT` | `--statsd-tags-format` | | Which tags format we should use. By default, we are using default vanilla statsd tags format but if you want to send directly to InfluxDB or Datadog, please specify it there. Possible options are `influxdb` and `datadog`. |
| `MTG_STATSD_TAGS` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. | | `MTG_STATSD_TAGS` | `--statsd-tags` | | Which tags should we send to statsd with our metrics. Please specify them as `key=value` pairs. |
+24
View File
@@ -0,0 +1,24 @@
# Security Policy
## Supported Versions
We support 2 tracks: 2.x and 1.x
| Version | Supported |
| ------- | ------------------ |
| 2.x | :white_check_mark: |
| 1.x | :interrobang: |
| < 1.0 | :x: |
1.x has adtag support. We do not plan any active development there but we guarantee:
1. Regular dependency updates
2. Updates for Golang versions
3. Security vulnerability fixes
4. Merging small PRs
2.x is in active development and have a full support.
## Reporting a Vulnerability
If you have found a vulnerability, please report about it to nineseconds@yandex.ru, telegram @9seconds or here in issues
+1 -2
View File
@@ -3,9 +3,8 @@ package antireplay
import ( import (
"sync" "sync"
"github.com/VictoriaMetrics/fastcache"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/VictoriaMetrics/fastcache"
) )
type CacheInterface interface { type CacheInterface interface {
+3 -4
View File
@@ -5,9 +5,6 @@ import (
"os" "os"
"time" "time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/9seconds/mtg/antireplay" "github.com/9seconds/mtg/antireplay"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/faketls" "github.com/9seconds/mtg/faketls"
@@ -18,9 +15,11 @@ import (
"github.com/9seconds/mtg/stats" "github.com/9seconds/mtg/stats"
"github.com/9seconds/mtg/telegram" "github.com/9seconds/mtg/telegram"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
) )
func Proxy() error { // nolint: funlen func Proxy() error { // nolint: funlen,cyclop
ctx := utils.GetSignalContext() ctx := utils.GetSignalContext()
atom := zap.NewAtomicLevel() atom := zap.NewAtomicLevel()
+2 -2
View File
@@ -9,7 +9,7 @@ import (
func Fatal(arg interface{}) { func Fatal(arg interface{}) {
if value, ok := arg.(error); ok { if value, ok := arg.(error); ok {
arg = fmt.Errorf("fatal error: %+v", value) arg = fmt.Errorf("fatal error: %+v", value) // nolint: errorlint
} }
PrintStderr(arg) PrintStderr(arg)
@@ -21,7 +21,7 @@ func PrintStderr(args ...interface{}) {
} }
func PrintStdout(args ...interface{}) { func PrintStdout(args ...interface{}) {
fmt.Println(args...) fmt.Println(args...) // nolint: forbidigo
} }
func PrintJSONStderr(data interface{}) { func PrintJSONStderr(data interface{}) {
+39 -37
View File
@@ -22,6 +22,8 @@ func (s SecretMode) String() string {
return "simple" return "simple"
case SecretModeSecured: case SecretModeSecured:
return "secured" return "secured"
case SecretModeTLS:
return "tls"
} }
return "tls" return "tls"
@@ -77,29 +79,29 @@ const (
type Config struct { type Config struct {
Bind *net.TCPAddr `json:"bind"` Bind *net.TCPAddr `json:"bind"`
PublicIPv4 *net.TCPAddr `json:"public_ipv4"` PublicIPv4 *net.TCPAddr `json:"public_ipv4"` // nolint: tagliatelle
PublicIPv6 *net.TCPAddr `json:"public_ipv6"` PublicIPv6 *net.TCPAddr `json:"public_ipv6"` // nolint: tagliatelle
StatsBind *net.TCPAddr `json:"stats_bind"` StatsBind *net.TCPAddr `json:"stats_bind"` // nolint: tagliatelle
StatsdAddr *net.TCPAddr `json:"stats_addr"` StatsdAddr *net.TCPAddr `json:"stats_addr"` // nolint: tagliatelle
StatsdTagsFormat *statsd.TagFormat `json:"statsd_tags_format"` StatsdTagsFormat *statsd.TagFormat `json:"statsd_tags_format"` // nolint: tagliatelle
StatsNamespace string `json:"stats_namespace"` StatsNamespace string `json:"stats_namespace"` // nolint: tagliatelle
CloakHost string `json:"cloak_host"` CloakHost string `json:"cloak_host"` // nolint: tagliatelle
StatsdTags map[string]string `json:"statsd_tags"` StatsdTags map[string]string `json:"statsd_tags"` // nolint: tagliatelle
WriteBuffer int `json:"write_buffer"` WriteBuffer int `json:"write_buffer"` // nolint: tagliatelle
ReadBuffer int `json:"read_buffer"` ReadBuffer int `json:"read_buffer"` // nolint: tagliatelle
CloakPort int `json:"cloak_port"` CloakPort int `json:"cloak_port"` // nolint: tagliatelle
AntiReplayMaxSize int `json:"anti_replay_max_size"` AntiReplayMaxSize int `json:"anti_replay_max_size"` // nolint: tagliatelle
MultiplexPerConnection int `json:"multiplex_per_connection"` MultiplexPerConnection int `json:"multiplex_per_connection"` // nolint: tagliatelle
Debug bool `json:"debug"` Debug bool `json:"debug"`
Verbose bool `json:"verbose"` Verbose bool `json:"verbose"`
SecretMode SecretMode `json:"secret_mode"` SecretMode SecretMode `json:"secret_mode"` // nolint: tagliatelle
PreferIP PreferIP `json:"prefer_ip"` PreferIP PreferIP `json:"prefer_ip"` // nolint: tagliatelle
NTPServers []string `json:"ntp_servers"` NTPServers []string `json:"ntp_servers"` // nolint: tagliatelle
Secret []byte `json:"secret"` Secret []byte `json:"secret"`
AdTag []byte `json:"adtag"` AdTag []byte `json:"adtag"`
@@ -144,7 +146,7 @@ func (c *Config) adjustProxyValue(value int) int {
fvalue := float64(value) fvalue := float64(value)
newValue := fvalue * 2 * math.Log(float64(c.MultiplexPerConnection)) newValue := fvalue * 2 * math.Log(float64(c.MultiplexPerConnection)) // nolint: gomnd
newValue = math.Ceil(newValue) newValue = math.Ceil(newValue)
newValue = math.Max(fvalue, newValue) newValue = math.Max(fvalue, newValue)
@@ -158,15 +160,15 @@ type Opt struct {
var C = Config{} var C = Config{}
func Init(options ...Opt) error { // nolint: gocyclo, funlen func Init(options ...Opt) error { // nolint: gocyclo, funlen, cyclop
for _, opt := range options { for _, opt := range options {
switch opt.Option { switch opt.Option {
case OptionTypeDebug: case OptionTypeDebug:
C.Debug = opt.Value.(bool) C.Debug = opt.Value.(bool) // nolint: forcetypeassert
case OptionTypeVerbose: case OptionTypeVerbose:
C.Verbose = opt.Value.(bool) C.Verbose = opt.Value.(bool) // nolint: forcetypeassert
case OptionTypePreferIP: case OptionTypePreferIP:
value := opt.Value.(string) value := opt.Value.(string) // nolint: forcetypeassert
switch value { switch value {
case "ipv4": case "ipv4":
C.PreferIP = PreferIPv4 C.PreferIP = PreferIPv4
@@ -176,25 +178,25 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen
return fmt.Errorf("incorrect direct IP mode %s", value) return fmt.Errorf("incorrect direct IP mode %s", value)
} }
case OptionTypeBind: case OptionTypeBind:
C.Bind = opt.Value.(*net.TCPAddr) C.Bind = opt.Value.(*net.TCPAddr) // nolint: forcetypeassert
case OptionTypePublicIPv4: case OptionTypePublicIPv4:
C.PublicIPv4 = opt.Value.(*net.TCPAddr) C.PublicIPv4 = opt.Value.(*net.TCPAddr) // nolint: forcetypeassert
if C.PublicIPv4 == nil { if C.PublicIPv4 == nil {
C.PublicIPv4 = &net.TCPAddr{} C.PublicIPv4 = &net.TCPAddr{}
} }
case OptionTypePublicIPv6: case OptionTypePublicIPv6:
C.PublicIPv6 = opt.Value.(*net.TCPAddr) C.PublicIPv6 = opt.Value.(*net.TCPAddr) // nolint: forcetypeassert
if C.PublicIPv6 == nil { if C.PublicIPv6 == nil {
C.PublicIPv6 = &net.TCPAddr{} C.PublicIPv6 = &net.TCPAddr{}
} }
case OptionTypeStatsBind: case OptionTypeStatsBind:
C.StatsBind = opt.Value.(*net.TCPAddr) C.StatsBind = opt.Value.(*net.TCPAddr) // nolint: forcetypeassert
case OptionTypeStatsNamespace: case OptionTypeStatsNamespace:
C.StatsNamespace = opt.Value.(string) C.StatsNamespace = opt.Value.(string) // nolint: forcetypeassert
case OptionTypeStatsdAddress: case OptionTypeStatsdAddress:
C.StatsdAddr = opt.Value.(*net.TCPAddr) C.StatsdAddr = opt.Value.(*net.TCPAddr) // nolint: forcetypeassert
case OptionTypeStatsdTagsFormat: case OptionTypeStatsdTagsFormat:
value := opt.Value.(string) value := opt.Value.(string) // nolint: forcetypeassert
switch value { switch value {
case "datadog": case "datadog":
C.StatsdTagsFormat = statsd.TagFormatDatadog C.StatsdTagsFormat = statsd.TagFormatDatadog
@@ -204,26 +206,26 @@ func Init(options ...Opt) error { // nolint: gocyclo, funlen
return fmt.Errorf("incorrect statsd tag %s", value) return fmt.Errorf("incorrect statsd tag %s", value)
} }
case OptionTypeStatsdTags: case OptionTypeStatsdTags:
C.StatsdTags = opt.Value.(map[string]string) C.StatsdTags = opt.Value.(map[string]string) // nolint: forcetypeassert
case OptionTypeWriteBufferSize: case OptionTypeWriteBufferSize:
C.WriteBuffer = int(opt.Value.(units.Base2Bytes)) C.WriteBuffer = int(opt.Value.(units.Base2Bytes)) // nolint: forcetypeassert
case OptionTypeReadBufferSize: case OptionTypeReadBufferSize:
C.ReadBuffer = int(opt.Value.(units.Base2Bytes)) C.ReadBuffer = int(opt.Value.(units.Base2Bytes)) // nolint: forcetypeassert
case OptionTypeCloakPort: case OptionTypeCloakPort:
C.CloakPort = int(opt.Value.(uint16)) C.CloakPort = int(opt.Value.(uint16)) // nolint: forcetypeassert
case OptionTypeAntiReplayMaxSize: case OptionTypeAntiReplayMaxSize:
C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes)) C.AntiReplayMaxSize = int(opt.Value.(units.Base2Bytes)) // nolint: forcetypeassert
case OptionTypeMultiplexPerConnection: case OptionTypeMultiplexPerConnection:
C.MultiplexPerConnection = int(opt.Value.(uint)) C.MultiplexPerConnection = int(opt.Value.(uint)) // nolint: forcetypeassert
case OptionTypeNTPServers: case OptionTypeNTPServers:
C.NTPServers = opt.Value.([]string) C.NTPServers = opt.Value.([]string) // nolint: forcetypeassert
if len(C.NTPServers) == 0 { if len(C.NTPServers) == 0 {
return errors.New("ntp server list is empty") return errors.New("ntp server list is empty")
} }
case OptionTypeSecret: case OptionTypeSecret:
C.Secret = opt.Value.([]byte) C.Secret = opt.Value.([]byte) // nolint: forcetypeassert
case OptionTypeAdtag: case OptionTypeAdtag:
C.AdTag = opt.Value.([]byte) C.AdTag = opt.Value.([]byte) // nolint: forcetypeassert
default: default:
return fmt.Errorf("unknown tag %v", opt.Option) return fmt.Errorf("unknown tag %v", opt.Option)
} }
+2 -2
View File
@@ -41,7 +41,7 @@ func fetchIP(ctx context.Context, network string) (net.IP, error) {
Timeout: ifconfigTimeout, Timeout: ifconfigTimeout,
Transport: &http.Transport{ Transport: &http.Transport{
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) {
return dialer.DialContext(ctx, network, addr) return dialer.DialContext(ctx, network, addr) // nolint: wrapcheck
}, },
}, },
} }
@@ -60,7 +60,7 @@ func fetchIP(ctx context.Context, network string) (net.IP, error) {
return nil, fmt.Errorf("cannot perform a request: %w", err) return nil, fmt.Errorf("cannot perform a request: %w", err)
} }
defer resp.Body.Close() // nolint: errcheck defer resp.Body.Close()
respDataBytes, err := ioutil.ReadAll(resp.Body) respDataBytes, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
+24 -16
View File
@@ -8,16 +8,16 @@ import (
) )
type URLs struct { type URLs struct {
TG string `json:"tg_url"` TG string `json:"tg_url"` // nolint: tagliatelle
TMe string `json:"tme_url"` TMe string `json:"tme_url"` // nolint: tagliatelle
TGQRCode string `json:"tg_qrcode"` TGQRCode string `json:"tg_qrcode"` // nolint: tagliatelle
TMeQRCode string `json:"tme_qrcode"` TMeQRCode string `json:"tme_qrcode"` // nolint: tagliatelle
} }
type IPURLs struct { type IPURLs struct {
IPv4 URLs `json:"ipv4"` IPv4 *URLs `json:"ipv4,omitempty"`
IPv6 URLs `json:"ipv6"` IPv6 *URLs `json:"ipv6,omitempty"`
BotSecret string `json:"secret_for_mtproxybot"` BotSecret string `json:"secret_for_mtproxybot"` // nolint: tagliatelle
} }
func GetURLs() (urls IPURLs) { func GetURLs() (urls IPURLs) {
@@ -32,25 +32,33 @@ func GetURLs() (urls IPURLs) {
secret = "ee" + hex.EncodeToString(C.Secret) + hex.EncodeToString([]byte(C.CloakHost)) secret = "ee" + hex.EncodeToString(C.Secret) + hex.EncodeToString([]byte(C.CloakHost))
} }
urls.IPv4 = makeURLs(C.PublicIPv4, secret) if C.PublicIPv4.IP != nil {
urls.IPv6 = makeURLs(C.PublicIPv6, secret) urls.IPv4 = makeURLs(C.PublicIPv4, secret)
}
if C.PublicIPv6.IP != nil {
urls.IPv6 = makeURLs(C.PublicIPv6, secret)
}
urls.BotSecret = hex.EncodeToString(C.Secret) urls.BotSecret = hex.EncodeToString(C.Secret)
return urls return urls
} }
func makeURLs(addr *net.TCPAddr, secret string) (urls URLs) { func makeURLs(addr *net.TCPAddr, secret string) *URLs {
urls := &URLs{}
values := url.Values{} values := url.Values{}
values.Set("server", addr.IP.String()) values.Set("server", addr.IP.String())
values.Set("port", strconv.Itoa(addr.Port)) values.Set("port", strconv.Itoa(addr.Port))
values.Set("secret", secret) values.Set("secret", secret)
urls.TG = makeTGURL(values) return &URLs{
urls.TMe = makeTMeURL(values) TG: makeTGURL(values),
urls.TGQRCode = makeQRCodeURL(urls.TG) TMe: makeTMeURL(values),
urls.TMeQRCode = makeQRCodeURL(urls.TG) TGQRCode: makeQRCodeURL(urls.TG),
TMeQRCode: makeQRCodeURL(urls.TMe),
return }
} }
func makeTGURL(values url.Values) string { func makeTGURL(values url.Values) string {
+2
View File
@@ -8,6 +8,8 @@ func (c ConnectionProtocol) String() string {
return "any" return "any"
case ConnectionProtocolIPv4: case ConnectionProtocolIPv4:
return "ipv4" return "ipv4"
case ConnectionProtocolIPv6:
return "ipv6"
} }
return "ipv6" return "ipv6"
+3 -1
View File
@@ -21,7 +21,9 @@ func (t ConnectionType) Tag() []byte {
return ConnectionTagAbridged return ConnectionTagAbridged
case ConnectionTypeIntermediate: case ConnectionTypeIntermediate:
return ConnectionTagIntermediate return ConnectionTagIntermediate
default: case ConnectionTypeSecure, ConnectionTypeUnknown:
return ConnectionTagSecure return ConnectionTagSecure
} }
return ConnectionTagSecure
} }
+7 -7
View File
@@ -2,6 +2,7 @@ package faketls
import ( import (
"bufio" "bufio"
"bytes"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@@ -48,13 +49,13 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
} }
conn := stream.NewFakeTLS(socket) conn := stream.NewFakeTLS(socket)
conn, err := c.ClientProtocol.Handshake(conn)
conn, err := c.ClientProtocol.Handshake(conn)
if err != nil { if err != nil {
return nil, err return nil, err // nolint: wrapcheck
} }
return conn, err return conn, err // nolint: wrapcheck
} }
func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error { func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
@@ -63,9 +64,7 @@ func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
return fmt.Errorf("cannot read initial record: %w", err) return fmt.Errorf("cannot read initial record: %w", err)
} }
buf := acquireBytesBuffer() buf := &bytes.Buffer{}
defer releaseBytesBuffer(buf)
helloRecord.Data.WriteBytes(buf) helloRecord.Data.WriteBytes(buf)
clientHello, err := tlstypes.ParseClientHello(buf.Bytes()) clientHello, err := tlstypes.ParseClientHello(buf.Bytes())
@@ -90,6 +89,7 @@ func (c *ClientProtocol) tlsHandshake(conn io.ReadWriter) error {
if antireplay.Cache.HasTLS(clientHello.Random[:]) { if antireplay.Cache.HasTLS(clientHello.Random[:]) {
stats.Stats.ReplayDetected() stats.Stats.ReplayDetected()
return errors.New("replay attack is detected") return errors.New("replay attack is detected")
} }
@@ -108,8 +108,8 @@ func (c *ClientProtocol) cloakHost(clientConn io.ReadWriteCloser) {
stats.Stats.CloakedRequest() stats.Stats.CloakedRequest()
addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort)) addr := net.JoinHostPort(config.C.CloakHost, strconv.Itoa(config.C.CloakPort))
hostConn, err := net.Dial("tcp", addr)
hostConn, err := net.Dial("tcp", addr)
if err != nil { if err != nil {
return return
} }
+4 -5
View File
@@ -26,7 +26,7 @@ func cloak(one, another io.ReadWriteCloser) {
another = rwc.NewPing(ctx, another, channelPing) another = rwc.NewPing(ctx, another, channelPing)
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
wg.Add(2) wg.Add(2) // nolint: gomnd
go cloakPipe(one, another, wg) go cloakPipe(one, another, wg)
@@ -53,9 +53,11 @@ func cloak(one, another io.ReadWriteCloser) {
return return
case <-lastActivityTimer.C: case <-lastActivityTimer.C:
cancel() cancel()
return return
case <-maxTimer.C: case <-maxTimer.C:
cancel() cancel()
return return
} }
} }
@@ -67,8 +69,5 @@ func cloak(one, another io.ReadWriteCloser) {
func cloakPipe(one io.Writer, another io.Reader, wg *sync.WaitGroup) { func cloakPipe(one io.Writer, another io.Reader, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
buf := acquireCloakBuffer() io.Copy(one, another) // nolint: errcheck
defer releaseCloakBuffer(buf)
io.CopyBuffer(one, another, *buf) // nolint: errcheck
} }
-39
View File
@@ -1,39 +0,0 @@
package faketls
import (
"bytes"
"sync"
)
const cloakBufferSize = 1024
var (
poolBytesBuffer = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
poolCloakBuffer = sync.Pool{
New: func() interface{} {
rv := make([]byte, cloakBufferSize)
return &rv
},
}
)
func acquireBytesBuffer() *bytes.Buffer {
return poolBytesBuffer.Get().(*bytes.Buffer)
}
func acquireCloakBuffer() *[]byte {
return poolCloakBuffer.Get().(*[]byte)
}
func releaseBytesBuffer(buf *bytes.Buffer) {
buf.Reset()
poolBytesBuffer.Put(buf)
}
func releaseCloakBuffer(buf *[]byte) {
poolCloakBuffer.Put(buf)
}
+24 -14
View File
@@ -1,21 +1,31 @@
module github.com/9seconds/mtg module github.com/9seconds/mtg
go 1.13 go 1.18
require ( require (
github.com/VictoriaMetrics/fastcache v1.5.7 github.com/VictoriaMetrics/fastcache v1.9.0
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
github.com/beevik/ntp v0.3.0 github.com/beevik/ntp v0.3.0
github.com/golang/protobuf v1.3.5 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/prometheus/client_golang v1.5.1 github.com/prometheus/client_golang v1.12.1
github.com/prometheus/procfs v0.0.11 // indirect github.com/prometheus/common v0.32.1 // indirect
github.com/smira/go-statsd v1.3.1 github.com/prometheus/procfs v0.7.3 // indirect
go.uber.org/zap v1.14.1 github.com/smira/go-statsd v1.3.2
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 go.uber.org/multierr v1.8.0 // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect go.uber.org/zap v1.21.0
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458 // indirect golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/alecthomas/kingpin.v2 v2.2.6
honnef.co/go/tools v0.0.1-2020.1.3 // indirect )
require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
) )
+394 -75
View File
@@ -1,65 +1,158 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 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=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VictoriaMetrics/fastcache v1.9.0 h1:oMwsS6c8abz98B7ytAewQ7M1ZN/Im/iwKoE1euaFvhs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/VictoriaMetrics/fastcache v1.9.0/go.mod h1:otoTS3xu+6IzF/qByjqzjp3rTuzM3Qf0ScU1UTj97iU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw= github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw=
github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -67,128 +160,354 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smira/go-statsd v1.3.1 h1:JalGiHNdK7GqVAPpg7j0Kwp2jZrz/fCg/B4ZuNuBY2w= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smira/go-statsd v1.3.1/go.mod h1:1srXJ9/pbnN04G8f4F1jUzsGOnwkPKXciyqpewGlkC4= github.com/smira/go-statsd v1.3.2 h1:1EeuzxNZ/TD9apbTOFSM9nulqfcsQFmT4u1A2DREabI=
github.com/smira/go-statsd v1.3.2/go.mod h1:1srXJ9/pbnN04G8f4F1jUzsGOnwkPKXciyqpewGlkC4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
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/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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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/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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458 h1:DgonIcqC7u+gVZX7lpuReBil5B/i8fvW/hAQdhT6/ao= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200319210407-521f4a0cd458/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+3 -3
View File
@@ -6,12 +6,11 @@ import (
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/mtproto" "github.com/9seconds/mtg/mtproto"
"github.com/9seconds/mtg/mtproto/rpc" "github.com/9seconds/mtg/mtproto/rpc"
"github.com/9seconds/mtg/protocol" "github.com/9seconds/mtg/protocol"
"go.uber.org/zap"
) )
const connectionTTL = time.Hour const connectionTTL = time.Hour
@@ -31,7 +30,7 @@ type connection struct {
channelConnDetach chan conntypes.ConnID channelConnDetach chan conntypes.ConnID
} }
func (c *connection) run() { func (c *connection) run() { // nolint: cyclop
defer c.Close() defer c.Close()
ttl := time.NewTimer(connectionTTL) ttl := time.NewTimer(connectionTTL)
@@ -90,6 +89,7 @@ func (c *connection) readLoop() {
response, err := rpc.ParseProxyResponse(packet) response, err := rpc.ParseProxyResponse(packet)
if err != nil { if err != nil {
c.logger.Debugw("Failed response", "error", err) c.logger.Debugw("Failed response", "error", err)
continue continue
} }
+1
View File
@@ -25,6 +25,7 @@ func (c *connectionList) get(conn *ProxyConn) (*connection, error) {
if err = newConn.Attach(conn); err != nil { if err = newConn.Attach(conn); err != nil {
newConn.Close() newConn.Close()
return nil, fmt.Errorf("cannot attach to the newly created connection: %w", err) return nil, fmt.Errorf("cannot attach to the newly created connection: %w", err)
} }
+1 -1
View File
@@ -18,7 +18,7 @@ func (h *hub) Register(req *protocol.TelegramRequest) (*ProxyConn, error) {
} }
func (h *hub) getMux(req *protocol.TelegramRequest) *mux { func (h *hub) getMux(req *protocol.TelegramRequest) *mux {
var key int32 = 32767 + int32(req.ClientProtocol.DC()) + 100000*int32(req.ClientProtocol.ConnectionProtocol()) key := 32767 + int32(req.ClientProtocol.DC()) + 100000*int32(req.ClientProtocol.ConnectionProtocol()) // nolint: gomnd
h.mutex.RLock() h.mutex.RLock()
m, ok := h.muxes[key] m, ok := h.muxes[key]
+1 -2
View File
@@ -7,11 +7,10 @@ import (
"strings" "strings"
"time" "time"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"github.com/9seconds/mtg/cli" "github.com/9seconds/mtg/cli"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
kingpin "gopkg.in/alecthomas/kingpin.v2"
) )
var version = "dev" // has to be set by ldflags var version = "dev" // has to be set by ldflags
+2 -2
View File
@@ -19,8 +19,8 @@ func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.PacketReadWriteC
} }
rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce) rpcNonceConn := packet.NewMtprotoFrame(conn, rpc.SeqNoNonce)
rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
rpcNonceReq, err := doRPCNonceRequest(rpcNonceConn)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot do nonce request: %w", err) return nil, fmt.Errorf("cannot do nonce request: %w", err)
} }
@@ -51,7 +51,7 @@ func doRPCNonceRequest(conn conntypes.BasePacketWriter) (*rpc.NonceRequest, erro
} }
if err := conn.Write(rpcNonceReq.Bytes()); err != nil { if err := conn.Write(rpcNonceReq.Bytes()); err != nil {
return nil, err return nil, err // nolint: wrapcheck
} }
return rpcNonceReq, nil return rpcNonceReq, nil
+1 -1
View File
@@ -7,7 +7,7 @@ const (
SeqNoHandshake = -1 SeqNoHandshake = -1
) )
// Different constants for RPC protocol // Different constants for RPC protocol.
var ( var (
TagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e} TagCloseExt = []byte{0xa2, 0x34, 0xb6, 0x5e}
TagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44} TagProxyAns = []byte{0x0d, 0xda, 0x03, 0x44}
+5 -5
View File
@@ -17,10 +17,10 @@ type HandshakeResponse struct {
func (r *HandshakeResponse) Bytes() []byte { func (r *HandshakeResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.Write(r.Type) // nolint: gosec buf.Write(r.Type)
buf.Write(r.Flags) // nolint: gosec buf.Write(r.Flags)
buf.Write(r.SenderPID) // nolint: gosec buf.Write(r.SenderPID)
buf.Write(r.PeerPID) // nolint: gosec buf.Write(r.PeerPID)
return buf.Bytes() return buf.Bytes()
} }
@@ -41,7 +41,7 @@ func (r *HandshakeResponse) Valid() error {
// NewHandshakeResponse constructs new handshake response from the given // NewHandshakeResponse constructs new handshake response from the given
// data. // data.
func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) { func NewHandshakeResponse(data []byte) (*HandshakeResponse, error) {
if len(data) != 32 { if len(data) != 32 { // nolint: gomnd
return nil, fmt.Errorf("incorrect handshake response length %d", len(data)) return nil, fmt.Errorf("incorrect handshake response length %d", len(data))
} }
+5 -5
View File
@@ -29,17 +29,17 @@ func (r *NonceRequest) Bytes() []byte {
// NewNonceRequest builds new none request based on proxy secret. // NewNonceRequest builds new none request based on proxy secret.
func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) { func NewNonceRequest(proxySecret []byte) (*NonceRequest, error) {
nonce := make([]byte, 16) nonce := make([]byte, 16) // nolint: gomnd
keySelector := make([]byte, 4) keySelector := make([]byte, 4) // nolint: gomnd
cryptoTS := make([]byte, 4) cryptoTS := make([]byte, 4) // nolint: gomnd
if _, err := rand.Read(nonce); err != nil { if _, err := rand.Read(nonce); err != nil {
return nil, fmt.Errorf("cannot generate nonce: %w", err) return nil, fmt.Errorf("cannot generate nonce: %w", err)
} }
copy(keySelector, proxySecret) copy(keySelector, proxySecret)
// 256 ^ 4 - do not know how to name
timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // 256 ^ 4 - do not know how to name timestamp := time.Now().Truncate(time.Second).Unix() % 4294967296 // nolint: gomnd
binary.LittleEndian.PutUint32(cryptoTS, uint32(timestamp)) binary.LittleEndian.PutUint32(cryptoTS, uint32(timestamp))
return &NonceRequest{ return &NonceRequest{
+7 -7
View File
@@ -15,13 +15,13 @@ type NonceResponse struct {
// Bytes returns serialized form of the nonce response. // Bytes returns serialized form of the nonce response.
func (r *NonceResponse) Bytes() []byte { func (r *NonceResponse) Bytes() []byte {
buf := &bytes.Buffer{} buf := bytes.Buffer{}
buf.Write(r.Type) // nolint: gosec buf.Write(r.Type)
buf.Write(r.KeySelector) // nolint: gosec buf.Write(r.KeySelector)
buf.Write(r.Crypto) // nolint: gosec buf.Write(r.Crypto)
buf.Write(r.CryptoTS) // nolint: gosec buf.Write(r.CryptoTS)
buf.Write(r.Nonce) // nolint: gosec buf.Write(r.Nonce)
return buf.Bytes() return buf.Bytes()
} }
@@ -44,7 +44,7 @@ func (r *NonceResponse) Valid(req *NonceRequest) error {
// NewNonceResponse build new nonce response based on the given data. // NewNonceResponse build new nonce response based on the given data.
func NewNonceResponse(data []byte) (*NonceResponse, error) { func NewNonceResponse(data []byte) (*NonceResponse, error) {
if len(data) != 32 { if len(data) != 32 { // nolint: gomnd
return nil, fmt.Errorf("unexpected message length %d", len(data)) return nil, fmt.Errorf("unexpected message length %d", len(data))
} }
+2 -2
View File
@@ -21,14 +21,14 @@ const (
var ProxyRequestFlagsEncryptedPrefix [8]byte var ProxyRequestFlagsEncryptedPrefix [8]byte
func (r ProxyRequestFlags) Bytes() []byte { func (r ProxyRequestFlags) Bytes() []byte {
converted := make([]byte, 4) converted := make([]byte, 4) // nolint: gomnd
binary.LittleEndian.PutUint32(converted, uint32(r)) binary.LittleEndian.PutUint32(converted, uint32(r))
return converted return converted
} }
func (r ProxyRequestFlags) String() string { func (r ProxyRequestFlags) String() string {
flags := make([]string, 0, 7) flags := make([]string, 0, 7) // nolint: gomnd
if r&ProxyRequestFlagsHasAdTag != 0 { if r&ProxyRequestFlagsHasAdTag != 0 {
flags = append(flags, "HAS_AD_TAG") flags = append(flags, "HAS_AD_TAG")
+1 -1
View File
@@ -24,7 +24,7 @@ type ProxyResponse struct {
func ParseProxyResponse(packet conntypes.Packet) (*ProxyResponse, error) { func ParseProxyResponse(packet conntypes.Packet) (*ProxyResponse, error) {
var response ProxyResponse var response ProxyResponse
if len(packet) < 4 { if len(packet) < 4 { // nolint: gomnd
return nil, fmt.Errorf("incorrect packet length: %d", len(packet)) return nil, fmt.Errorf("incorrect packet length: %d", len(packet))
} }
+3 -3
View File
@@ -5,17 +5,16 @@ import (
"math/rand" "math/rand"
"time" "time"
"github.com/9seconds/mtg/config"
"github.com/beevik/ntp" "github.com/beevik/ntp"
"go.uber.org/zap" "go.uber.org/zap"
"github.com/9seconds/mtg/config"
) )
const autoUpdatePeriod = time.Minute const autoUpdatePeriod = time.Minute
// Fetch fetches the data on time drift. // Fetch fetches the data on time drift.
func Fetch() (time.Duration, error) { func Fetch() (time.Duration, error) {
url := config.C.NTPServers[rand.Intn(len(config.C.NTPServers))] url := config.C.NTPServers[rand.Intn(len(config.C.NTPServers))] // nolint: gosec
resp, err := ntp.Query(url) resp, err := ntp.Query(url)
if err != nil { if err != nil {
@@ -40,6 +39,7 @@ func AutoUpdate() {
diff, err := Fetch() diff, err := Fetch()
if err != nil { if err != nil {
logger.Debugw("Cannot fetch time from NTP", "error", err) logger.Debugw("Cannot fetch time from NTP", "error", err)
continue continue
} }
+6 -5
View File
@@ -45,14 +45,14 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
} }
decHasher := sha256.New() decHasher := sha256.New()
decHasher.Write(fm.Key()) // nolint: errcheck decHasher.Write(fm.Key())
decHasher.Write(config.C.Secret) // nolint: errcheck decHasher.Write(config.C.Secret)
decryptor := utils.MakeStreamCipher(decHasher.Sum(nil), fm.IV()) decryptor := utils.MakeStreamCipher(decHasher.Sum(nil), fm.IV())
invertedFrame := fm.Invert() invertedFrame := fm.Invert()
encHasher := sha256.New() encHasher := sha256.New()
encHasher.Write(invertedFrame.Key()) // nolint: errcheck encHasher.Write(invertedFrame.Key())
encHasher.Write(config.C.Secret) // nolint: errcheck encHasher.Write(config.C.Secret)
encryptor := utils.MakeStreamCipher(encHasher.Sum(nil), invertedFrame.IV()) encryptor := utils.MakeStreamCipher(encHasher.Sum(nil), invertedFrame.IV())
decryptedFrame := Frame{} decryptedFrame := Frame{}
@@ -84,6 +84,7 @@ func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conn
replayKey := decryptedFrame.Unique() replayKey := decryptedFrame.Unique()
if antireplay.Cache.HasObfuscated2(replayKey) { if antireplay.Cache.HasObfuscated2(replayKey) {
stats.Stats.ReplayDetected() stats.Stats.ReplayDetected()
return nil, errors.New("replay attack is detected") return nil, errors.New("replay attack is detected")
} }
@@ -105,7 +106,7 @@ type handshakeReader struct {
} }
func (h handshakeReader) Read(p []byte) (int, error) { func (h handshakeReader) Read(p []byte) (int, error) {
return h.parent.ReadTimeout(p, clientProtocolHandshakeTimeout) return h.parent.ReadTimeout(p, clientProtocolHandshakeTimeout) // nolint: wrapcheck
} }
func MakeClientProtocol() protocol.ClientProtocol { func MakeClientProtocol() protocol.ClientProtocol {
+1 -1
View File
@@ -15,7 +15,7 @@ const (
frameLen = 64 frameLen = 64
) )
// [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd] // [frameOffsetFirst:frameOffsetKey:frameOffsetIV:frameOffsetMagic:frameOffsetDC:frameOffsetEnd].
type Frame struct { type Frame struct {
data [frameLen]byte data [frameLen]byte
} }
+5 -5
View File
@@ -47,17 +47,17 @@ func generateFrame(cp protocol.ClientProtocol) (fm Frame) {
continue continue
} }
if data[0] == 0xef { if data[0] == 0xef { // nolint: gomnd
continue continue
} }
val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) // nolint: gomnd, lll
if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { // nolint: lll
continue continue
} }
val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) // nolint: gomnd
if val == 0x00000000 { if val == 0x00000000 { // nolint: gomnd
continue continue
} }
+1 -2
View File
@@ -3,9 +3,8 @@ package protocol
import ( import (
"context" "context"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type TelegramRequest struct { type TelegramRequest struct {
+6 -10
View File
@@ -4,11 +4,9 @@ import (
"io" "io"
"sync" "sync"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/obfuscated2" "github.com/9seconds/mtg/obfuscated2"
"github.com/9seconds/mtg/protocol" "github.com/9seconds/mtg/protocol"
"go.uber.org/zap"
) )
const directPipeBufferSize = 1024 const directPipeBufferSize = 1024
@@ -16,19 +14,17 @@ const directPipeBufferSize = 1024
func directConnection(request *protocol.TelegramRequest) error { func directConnection(request *protocol.TelegramRequest) error {
telegramConnRaw, err := obfuscated2.TelegramProtocol(request) telegramConnRaw, err := obfuscated2.TelegramProtocol(request)
if err != nil { if err != nil {
return err return err // nolint: wrapcheck
} }
telegramConn := telegramConnRaw.(conntypes.StreamReadWriteCloser) defer telegramConnRaw.Close()
defer telegramConn.Close()
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
wg.Add(2) wg.Add(2) // nolint: gomnd
go directPipe(telegramConn, request.ClientConn, wg, request.Logger) go directPipe(telegramConnRaw, request.ClientConn, wg, request.Logger)
go directPipe(request.ClientConn, telegramConn, wg, request.Logger) go directPipe(request.ClientConn, telegramConnRaw, wg, request.Logger)
wg.Wait() wg.Wait()
+9 -6
View File
@@ -3,17 +3,17 @@ package proxy
import ( import (
"sync" "sync"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/protocol" "github.com/9seconds/mtg/protocol"
"github.com/9seconds/mtg/wrappers/packetack" "github.com/9seconds/mtg/wrappers/packetack"
"go.uber.org/zap"
) )
func middleConnection(request *protocol.TelegramRequest) { func middleConnection(request *protocol.TelegramRequest) {
telegramConn, err := packetack.NewProxy(request) telegramConn, err := packetack.NewProxy(request)
if err != nil { if err != nil {
request.Logger.Debugw("Cannot dial to Telegram", "error", err) request.Logger.Debugw("Cannot dial to Telegram", "error", err)
return return
} }
defer telegramConn.Close() defer telegramConn.Close()
@@ -27,12 +27,12 @@ func middleConnection(request *protocol.TelegramRequest) {
clientConn = packetack.NewClientIntermediate(request.ClientConn) clientConn = packetack.NewClientIntermediate(request.ClientConn)
case conntypes.ConnectionTypeSecure: case conntypes.ConnectionTypeSecure:
clientConn = packetack.NewClientIntermediateSecure(request.ClientConn) clientConn = packetack.NewClientIntermediateSecure(request.ClientConn)
default: case conntypes.ConnectionTypeUnknown:
panic("unknown connection type") panic("unknown connection type")
} }
wg := &sync.WaitGroup{} wg := &sync.WaitGroup{}
wg.Add(2) wg.Add(2) // nolint: gomnd
go middlePipe(telegramConn, clientConn, wg, request.Logger) go middlePipe(telegramConn, clientConn, wg, request.Logger)
@@ -44,7 +44,8 @@ func middleConnection(request *protocol.TelegramRequest) {
func middlePipe(dst conntypes.PacketAckWriteCloser, func middlePipe(dst conntypes.PacketAckWriteCloser,
src conntypes.PacketAckReadCloser, src conntypes.PacketAckReadCloser,
wg *sync.WaitGroup, wg *sync.WaitGroup,
logger *zap.SugaredLogger) { logger *zap.SugaredLogger,
) {
defer func() { defer func() {
dst.Close() dst.Close()
src.Close() src.Close()
@@ -53,15 +54,17 @@ func middlePipe(dst conntypes.PacketAckWriteCloser,
for { for {
acks := conntypes.ConnectionAcks{} acks := conntypes.ConnectionAcks{}
packet, err := src.Read(&acks)
packet, err := src.Read(&acks)
if err != nil { if err != nil {
logger.Debugw("Cannot read packet", "error", err) logger.Debugw("Cannot read packet", "error", err)
return return
} }
if err = dst.Write(packet, &acks); err != nil { if err = dst.Write(packet, &acks); err != nil {
logger.Debugw("Cannot send packet", "error", err) logger.Debugw("Cannot send packet", "error", err)
return return
} }
} }
+3 -3
View File
@@ -4,14 +4,13 @@ import (
"context" "context"
"net" "net"
"go.uber.org/zap"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/protocol" "github.com/9seconds/mtg/protocol"
"github.com/9seconds/mtg/stats" "github.com/9seconds/mtg/stats"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
"github.com/9seconds/mtg/wrappers/stream" "github.com/9seconds/mtg/wrappers/stream"
"go.uber.org/zap"
) )
type Proxy struct { type Proxy struct {
@@ -53,6 +52,7 @@ func (p *Proxy) accept(conn net.Conn) {
if err := utils.InitTCP(conn, config.C.ClientReadBuffer(), config.C.ClientWriteBuffer()); err != nil { if err := utils.InitTCP(conn, config.C.ClientReadBuffer(), config.C.ClientWriteBuffer()); err != nil {
logger.Errorw("Cannot initialize client TCP connection", "error", err) logger.Errorw("Cannot initialize client TCP connection", "error", err)
return return
} }
@@ -66,8 +66,8 @@ func (p *Proxy) accept(conn net.Conn) {
defer clientConn.Close() defer clientConn.Close()
clientProtocol := p.ClientProtocolMaker() clientProtocol := p.ClientProtocolMaker()
clientConn, err := clientProtocol.Handshake(clientConn)
clientConn, err := clientProtocol.Handshake(clientConn)
if err != nil { if err != nil {
stats.Stats.AuthenticationFailed() stats.Stats.AuthenticationFailed()
logger.Warnw("Cannot perform client handshake", "error", err) logger.Warnw("Cannot perform client handshake", "error", err)
+1 -1
View File
@@ -32,7 +32,7 @@ func Init(ctx context.Context) error {
go func() { go func() {
<-ctx.Done() <-ctx.Done()
srv.Shutdown(context.Background()) // nolint: errcheck srv.Shutdown(context.Background()) // nolint: errcheck, contextcheck
}() }()
Stats = multiStats(stats) Stats = multiStats(stats)
+9 -5
View File
@@ -5,11 +5,10 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
) )
type statsPrometheus struct { type statsPrometheus struct {
@@ -40,7 +39,8 @@ func (s *statsPrometheus) ClientDisconnected(connectionType conntypes.Connection
func (s *statsPrometheus) changeConnections(connectionType conntypes.ConnectionType, func (s *statsPrometheus) changeConnections(connectionType conntypes.ConnectionType,
addr *net.TCPAddr, addr *net.TCPAddr,
increment float64) { increment float64,
) {
labels := [...]string{ labels := [...]string{
"intermediate", "intermediate",
"ipv4", "ipv4",
@@ -51,10 +51,14 @@ func (s *statsPrometheus) changeConnections(connectionType conntypes.ConnectionT
labels[0] = "abridged" labels[0] = "abridged"
case conntypes.ConnectionTypeSecure: case conntypes.ConnectionTypeSecure:
labels[0] = "secured" labels[0] = "secured"
case conntypes.ConnectionTypeIntermediate:
labels[0] = "intermediate"
case conntypes.ConnectionTypeUnknown:
panic("unknown connection type")
} }
if addr.IP.To4() == nil { if addr.IP.To4() == nil {
labels[1] = "ipv6" // nolint: goconst labels[1] = "ipv6"
} }
s.connections.WithLabelValues(labels[:]...).Add(increment) s.connections.WithLabelValues(labels[:]...).Add(increment)
+13 -11
View File
@@ -8,11 +8,10 @@ import (
"sync" "sync"
"time" "time"
statsd "github.com/smira/go-statsd"
"go.uber.org/zap"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
statsd "github.com/smira/go-statsd"
"go.uber.org/zap"
) )
var ( var (
@@ -84,15 +83,17 @@ func (s *statsStatsd) ClientDisconnected(connectionType conntypes.ConnectionType
} }
func (s *statsStatsd) changeConnections(connectionType conntypes.ConnectionType, addr *net.TCPAddr, increment int64) { func (s *statsStatsd) changeConnections(connectionType conntypes.ConnectionType, addr *net.TCPAddr, increment int64) {
tags := make([]*statsStatsdTag, 0, 2) tags := make([]*statsStatsdTag, 0, 2) // nolint: gomnd
switch connectionType { switch connectionType {
case conntypes.ConnectionTypeAbridged: case conntypes.ConnectionTypeAbridged:
tags = append(tags, tagConnectionTypeAbridged) tags = append(tags, tagConnectionTypeAbridged)
case conntypes.ConnectionTypeIntermediate: case conntypes.ConnectionTypeIntermediate:
tags = append(tags, tagConnectionTypeIntermediate) tags = append(tags, tagConnectionTypeIntermediate)
default: case conntypes.ConnectionTypeSecure:
tags = append(tags, tagConnectionTypeSecured) tags = append(tags, tagConnectionTypeSecured)
case conntypes.ConnectionTypeUnknown:
panic("Unknown connection type")
} }
if addr.IP.To4() == nil { if addr.IP.To4() == nil {
@@ -167,17 +168,18 @@ func (s *statsStatsd) prepareVals(metric string, tags []*statsStatsdTag) (string
func (s *statsStatsd) initGauge(metric, key string, tags []statsd.Tag) { func (s *statsStatsd) initGauge(metric, key string, tags []statsd.Tag) {
s.seenMutex.RLock() s.seenMutex.RLock()
_, ok := s.seen[key] if _, ok := s.seen[key]; ok {
s.seenMutex.RUnlock() s.seenMutex.RUnlock()
if ok {
return return
} else { // nolint: golint,revive
s.seenMutex.RUnlock()
} }
s.seenMutex.Lock() s.seenMutex.Lock()
defer s.seenMutex.Unlock() defer s.seenMutex.Unlock()
if _, ok = s.seen[key]; !ok { if _, ok := s.seen[key]; !ok {
s.seen[key] = struct{}{} s.seen[key] = struct{}{}
s.client.Gauge(metric, 0, tags...) s.client.Gauge(metric, 0, tags...)
} }
@@ -192,8 +194,8 @@ func newStatsStatsd() Interface {
return &statsStatsd{ return &statsStatsd{
seen: make(map[string]struct{}), seen: make(map[string]struct{}),
client: statsd.NewClient(config.C.StatsdAddr.String(), client: statsd.NewClient(config.C.StatsdAddr.String(),
statsd.SendLoopCount(2), statsd.SendLoopCount(2), // nolint: gomnd
statsd.ReconnectInterval(10*time.Second), statsd.ReconnectInterval(10*time.Second), // nolint: gomnd
statsd.Logger(logger), statsd.Logger(logger),
statsd.MetricPrefix(prefix), statsd.MetricPrefix(prefix),
statsd.TagStyle(config.C.StatsdTagsFormat), statsd.TagStyle(config.C.StatsdTagsFormat),
+4 -4
View File
@@ -74,12 +74,12 @@ func getAddresses(url string) (map[conntypes.DC][]string, conntypes.DC, error) {
} }
func addressesParseProxyFor(text string) (string, conntypes.DC, error) { func addressesParseProxyFor(text string) (string, conntypes.DC, error) {
chunks := addressesProxyForSplitter.Split(text, 3) chunks := addressesProxyForSplitter.Split(text, 3) // nolint: gomnd
if len(chunks) != 3 || chunks[0] != "proxy_for" { if len(chunks) != 3 || chunks[0] != "proxy_for" {
return "", 0, fmt.Errorf("incorrect config %s", text) return "", 0, fmt.Errorf("incorrect config %s", text)
} }
dc, err := strconv.ParseInt(chunks[1], 10, 16) dc, err := strconv.ParseInt(chunks[1], 10, 16) // nolint: gomnd
if err != nil { if err != nil {
return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err) return "", 0, fmt.Errorf("incorrect config '%s': %w", text, err)
} }
@@ -93,14 +93,14 @@ func addressesParseProxyFor(text string) (string, conntypes.DC, error) {
} }
func addressesParseDefault(text string) (conntypes.DC, error) { func addressesParseDefault(text string) (conntypes.DC, error) {
chunks := addressesProxyForSplitter.Split(text, 2) chunks := addressesProxyForSplitter.Split(text, 2) // nolint: gomnd
if len(chunks) != 2 || chunks[0] != "default" { if len(chunks) != 2 || chunks[0] != "default" {
return 0, fmt.Errorf("incorrect config '%s'", text) return 0, fmt.Errorf("incorrect config '%s'", text)
} }
dcString := strings.TrimRight(chunks[1], ";") dcString := strings.TrimRight(chunks[1], ";")
dc, err := strconv.ParseInt(dcString, 10, 16) dc, err := strconv.ParseInt(dcString, 10, 16) // nolint: gomnd
if err != nil { if err != nil {
return 0, fmt.Errorf("incorrect config '%s': %w", text, err) return 0, fmt.Errorf("incorrect config '%s': %w", text, err)
} }
+6 -2
View File
@@ -1,6 +1,7 @@
package api package api
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@@ -18,7 +19,10 @@ var httpClient = http.Client{
} }
func request(url string) (io.ReadCloser, error) { func request(url string) (io.ReadCloser, error) {
req, err := http.NewRequest("GET", url, nil) ctx, cancel := context.WithTimeout(context.Background(), apiHTTPTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -36,5 +40,5 @@ func request(url string) (io.ReadCloser, error) {
return nil, fmt.Errorf("cannot perform a request: %w", err) return nil, fmt.Errorf("cannot perform a request: %w", err)
} }
return resp.Body, err return resp.Body, err // nolint: wrapcheck
} }
+9 -6
View File
@@ -5,12 +5,11 @@ import (
"math/rand" "math/rand"
"net" "net"
"go.uber.org/zap"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
"github.com/9seconds/mtg/wrappers/stream" "github.com/9seconds/mtg/wrappers/stream"
"go.uber.org/zap"
) )
type baseTelegram struct { type baseTelegram struct {
@@ -29,16 +28,19 @@ func (b *baseTelegram) Secret() []byte {
} }
func (b *baseTelegram) dial(dc conntypes.DC, func (b *baseTelegram) dial(dc conntypes.DC,
protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { protocol conntypes.ConnectionProtocol,
) (conntypes.StreamReadWriteCloser, error) {
for _, addr := range b.getAddresses(dc, protocol) { for _, addr := range b.getAddresses(dc, protocol) {
conn, err := b.dialer.Dial("tcp", addr) conn, err := b.dialer.Dial("tcp", addr)
if err != nil { if err != nil {
b.logger.Infow("Cannot dial to Telegram", "address", addr, "error", err) b.logger.Infow("Cannot dial to Telegram", "address", addr, "error", err)
continue continue
} }
if err := utils.InitTCP(conn, config.C.ProxyReadBuffer(), config.C.ProxyWriteBuffer()); err != nil { if err := utils.InitTCP(conn, config.C.ProxyReadBuffer(), config.C.ProxyWriteBuffer()); err != nil {
b.logger.Infow("Cannot initialize TCP socket", "address", addr, "error", err) b.logger.Infow("Cannot initialize TCP socket", "address", addr, "error", err)
continue continue
} }
@@ -49,7 +51,7 @@ func (b *baseTelegram) dial(dc conntypes.DC,
} }
func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.ConnectionProtocol) []string { func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.ConnectionProtocol) []string {
addresses := make([]string, 0, 2) addresses := make([]string, 0, 2) // nolint: gomnd
protos := []conntypes.ConnectionProtocol{ protos := []conntypes.ConnectionProtocol{
conntypes.ConnectionProtocolIPv6, conntypes.ConnectionProtocolIPv6,
conntypes.ConnectionProtocolIPv4, conntypes.ConnectionProtocolIPv4,
@@ -73,7 +75,8 @@ func (b *baseTelegram) getAddresses(dc conntypes.DC, protocol conntypes.Connecti
} }
func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string, func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,
dc, defaultDC conntypes.DC) string { dc, defaultDC conntypes.DC,
) string {
addrs, ok := addresses[dc] addrs, ok := addresses[dc]
if !ok { if !ok {
addrs = addresses[defaultDC] addrs = addresses[defaultDC]
@@ -83,7 +86,7 @@ func (b *baseTelegram) chooseAddress(addresses map[conntypes.DC][]string,
case len(addrs) == 1: case len(addrs) == 1:
return addrs[0] return addrs[0]
case len(addrs) > 1: case len(addrs) > 1:
return addrs[rand.Intn(len(addrs))] return addrs[rand.Intn(len(addrs))] // nolint: gosec
} }
return "" return ""
+2 -1
View File
@@ -29,7 +29,8 @@ type directTelegram struct {
} }
func (d *directTelegram) Dial(dc conntypes.DC, func (d *directTelegram) Dial(dc conntypes.DC,
protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { protocol conntypes.ConnectionProtocol,
) (conntypes.StreamReadWriteCloser, error) {
switch { switch {
case dc < 0: case dc < 0:
dc = -dc dc = -dc
+3 -3
View File
@@ -5,10 +5,9 @@ import (
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/telegram/api" "github.com/9seconds/mtg/telegram/api"
"go.uber.org/zap"
) )
const middleTelegramBackgroundUpdateEvery = time.Hour const middleTelegramBackgroundUpdateEvery = time.Hour
@@ -64,7 +63,8 @@ func (m *middleTelegram) backgroundUpdate() {
} }
func (m *middleTelegram) Dial(dc conntypes.DC, func (m *middleTelegram) Dial(dc conntypes.DC,
protocol conntypes.ConnectionProtocol) (conntypes.StreamReadWriteCloser, error) { protocol conntypes.ConnectionProtocol,
) (conntypes.StreamReadWriteCloser, error) {
if dc == 0 { if dc == 0 {
dc = conntypes.DCDefaultIdx dc = conntypes.DCDefaultIdx
} }
+10 -6
View File
@@ -20,9 +20,9 @@ const (
type CipherSuiteType uint8 type CipherSuiteType uint8
const ( const (
CipherSuiteType_TLS_AES_128_GCM_SHA256 CipherSuiteType = iota // nolint: stylecheck, golint CipherSuiteType_TLS_AES_128_GCM_SHA256 CipherSuiteType = iota // nolint: stylecheck,golint,revive
CipherSuiteType_TLS_AES_256_GCM_SHA384 // nolint: stylecheck, golint CipherSuiteType_TLS_AES_256_GCM_SHA384 // nolint: stylecheck,golint,revive
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256 // nolint: stylecheck, golint CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256 // nolint: stylecheck,golint,revive
) )
func (c CipherSuiteType) Bytes() []byte { func (c CipherSuiteType) Bytes() []byte {
@@ -31,6 +31,8 @@ func (c CipherSuiteType) Bytes() []byte {
return CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes return CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes
case CipherSuiteType_TLS_AES_256_GCM_SHA384: case CipherSuiteType_TLS_AES_256_GCM_SHA384:
return CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes return CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes
case CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256:
return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes
} }
return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes return CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes
@@ -46,6 +48,8 @@ func (v Version) Bytes() []byte {
return Version12Bytes return Version12Bytes
case Version11: case Version11:
return Version11Bytes return Version11Bytes
case Version10, VersionUnknown:
return Version10Bytes
} }
return Version10Bytes return Version10Bytes
@@ -65,9 +69,9 @@ var (
Version12Bytes = []byte{0x03, 0x03} Version12Bytes = []byte{0x03, 0x03}
Version13Bytes = []byte{0x03, 0x04} Version13Bytes = []byte{0x03, 0x04}
CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes = []byte{0x13, 0x01} // nolint: stylecheck, golint CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes = []byte{0x13, 0x01} // nolint: stylecheck,golint,revive
CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes = []byte{0x13, 0x02} // nolint: stylecheck, golint CipherSuiteType_TLS_AES_256_GCM_SHA384_Bytes = []byte{0x13, 0x02} // nolint: stylecheck,golint,revive
CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes = []byte{0x13, 0x03} // nolint; stylecheck, golint CipherSuiteType_TLS_CHACHA20_POLY1305_SHA256_Bytes = []byte{0x13, 0x03} // nolint: stylecheck,golint,revive
) )
type Byter interface { type Byter interface {
+5 -6
View File
@@ -1,6 +1,7 @@
package tlstypes package tlstypes
import ( import (
"bytes"
"io" "io"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
@@ -15,8 +16,7 @@ type Handshake struct {
} }
func (h *Handshake) WriteBytes(writer io.Writer) { func (h *Handshake) WriteBytes(writer io.Writer) {
packetBuf := acquireBytesBuffer() packetBuf := bytes.Buffer{}
defer releaseBytesBuffer(packetBuf)
writer.Write([]byte{byte(h.Type)}) // nolint: errcheck writer.Write([]byte{byte(h.Type)}) // nolint: errcheck
@@ -24,7 +24,7 @@ func (h *Handshake) WriteBytes(writer io.Writer) {
packetBuf.Write(h.Random[:]) packetBuf.Write(h.Random[:])
packetBuf.WriteByte(byte(len(h.SessionID))) packetBuf.WriteByte(byte(len(h.SessionID)))
packetBuf.Write(h.SessionID) packetBuf.Write(h.SessionID)
h.Tail.WriteBytes(packetBuf) h.Tail.WriteBytes(&packetBuf)
sizeUint24 := utils.ToUint24(uint32(packetBuf.Len())) sizeUint24 := utils.ToUint24(uint32(packetBuf.Len()))
sizeUint24Bytes := sizeUint24[:] sizeUint24Bytes := sizeUint24[:]
@@ -35,10 +35,9 @@ func (h *Handshake) WriteBytes(writer io.Writer) {
} }
func (h *Handshake) Len() int { func (h *Handshake) Len() int {
buf := acquireBytesBuffer() buf := bytes.Buffer{}
defer releaseBytesBuffer(buf)
h.WriteBytes(buf) h.WriteBytes(&buf)
return buf.Len() return buf.Len()
} }
-23
View File
@@ -1,23 +0,0 @@
package tlstypes
import (
"bytes"
"sync"
)
var (
poolBytesBuffer = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
)
func acquireBytesBuffer() *bytes.Buffer {
return poolBytesBuffer.Get().(*bytes.Buffer)
}
func releaseBytesBuffer(buf *bytes.Buffer) {
buf.Reset()
poolBytesBuffer.Put(buf)
}
+6 -7
View File
@@ -8,9 +8,8 @@ import (
"io" "io"
mrand "math/rand" mrand "math/rand"
"golang.org/x/crypto/curve25519"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"golang.org/x/crypto/curve25519"
) )
type ServerHello struct { type ServerHello struct {
@@ -37,8 +36,8 @@ func (s ServerHello) WelcomePacket() []byte {
} }
recChangeCipher.WriteBytes(buf) recChangeCipher.WriteBytes(buf)
hostCert := make([]byte, 1024+mrand.Intn(3092)) hostCert := make([]byte, 1024+mrand.Intn(3092)) // nolint: gosec, gomnd
rand.Read(hostCert) // nolint: errcheck rand.Read(hostCert) // nolint: errcheck
recData := Record{ recData := Record{
Type: RecordTypeApplicationData, Type: RecordTypeApplicationData,
@@ -50,8 +49,8 @@ func (s ServerHello) WelcomePacket() []byte {
packet := buf.Bytes() packet := buf.Bytes()
mac := hmac.New(sha256.New, config.C.Secret) mac := hmac.New(sha256.New, config.C.Secret)
mac.Write(s.clientHello.Random[:]) // nolint: errcheck mac.Write(s.clientHello.Random[:])
mac.Write(packet) // nolint: errcheck mac.Write(packet)
copy(packet[11:], mac.Sum(nil)) copy(packet[11:], mac.Sum(nil))
return packet return packet
@@ -68,7 +67,7 @@ func NewServerHello(clientHello *ClientHello) *ServerHello {
copy(rv.SessionID, clientHello.SessionID) copy(rv.SessionID, clientHello.SessionID)
tail := bytes.NewBuffer(CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes) tail := bytes.NewBuffer(CipherSuiteType_TLS_AES_128_GCM_SHA256_Bytes)
tail.WriteByte(0x00) // no compression tail.WriteByte(0x00) // nolint: gomnd // no compression
makeTLSExtensions(tail) makeTLSExtensions(tail)
rv.Tail = RawBytes(tail.Bytes()) rv.Tail = RawBytes(tail.Bytes())
+2 -9
View File
@@ -3,13 +3,10 @@ package utils
import ( import (
"fmt" "fmt"
"net" "net"
"time"
) )
const tcpKeepAlivePingPeriod = 2 * time.Second func InitTCP(conn net.Conn, readBufferSize, writeBufferSize int) error {
tcpConn := conn.(*net.TCPConn) // nolint: forcetypeassert
func InitTCP(conn net.Conn, readBufferSize int, writeBufferSize int) error {
tcpConn := conn.(*net.TCPConn)
if err := tcpConn.SetNoDelay(true); err != nil { if err := tcpConn.SetNoDelay(true); err != nil {
return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err) return fmt.Errorf("cannot set TCP_NO_DELAY: %w", err)
@@ -27,9 +24,5 @@ func InitTCP(conn net.Conn, readBufferSize int, writeBufferSize int) error {
return fmt.Errorf("cannot enable keep-alive: %w", err) return fmt.Errorf("cannot enable keep-alive: %w", err)
} }
if err := tcpConn.SetKeepAlivePeriod(tcpKeepAlivePingPeriod); err != nil {
return fmt.Errorf("cannot set keep-alive period: %w", err)
}
return nil return nil
} }
+1 -1
View File
@@ -11,7 +11,7 @@ func ReadFull(src io.Reader) (rv []byte, err error) {
for n == len(buf) { for n == len(buf) {
n, err = src.Read(buf) n, err = src.Read(buf)
if err != nil { if err != nil {
return nil, err return nil, err // nolint: wrapcheck
} }
rv = append(rv, buf[:n]...) rv = append(rv, buf[:n]...)
+1 -1
View File
@@ -6,7 +6,7 @@ func ReverseBytes(data []byte) []byte {
rv := make([]byte, dataLen) rv := make([]byte, dataLen)
rv[dataLen/2] = data[dataLen/2] rv[dataLen/2] = data[dataLen/2]
for i := dataLen/2 - 1; i >= 0; i-- { for i := dataLen/2 - 1; i >= 0; i-- { // nolint: gomnd
opp := dataLen - i - 1 opp := dataLen - i - 1
rv[i], rv[opp] = data[opp], data[i] rv[i], rv[opp] = data[opp], data[i]
} }
+1
View File
@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package utils package utils
+1
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows // +build windows
package utils package utils
+1
View File
@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package utils package utils
+1
View File
@@ -1,3 +1,4 @@
//go:build windows
// +build windows // +build windows
package utils package utils
+2 -1
View File
@@ -6,6 +6,7 @@ import (
) )
func MakeStreamCipher(key, iv []byte) cipher.Stream { func MakeStreamCipher(key, iv []byte) cipher.Stream {
block, _ := aes.NewCipher(key) // nolint: gosec block, _ := aes.NewCipher(key)
return cipher.NewCTR(block, iv) return cipher.NewCTR(block, iv)
} }
+2 -2
View File
@@ -3,9 +3,9 @@ package utils
type Uint24 [3]byte type Uint24 [3]byte
func ToUint24(number uint32) Uint24 { func ToUint24(number uint32) Uint24 {
return Uint24{byte(number), byte(number >> 8), byte(number >> 16)} return Uint24{byte(number), byte(number >> 8), byte(number >> 16)} // nolint: gomnd
} }
func FromUint24(number Uint24) uint32 { func FromUint24(number Uint24) uint32 {
return uint32(number[0]) + (uint32(number[1]) << 8) + (uint32(number[2]) << 16) return uint32(number[0]) + (uint32(number[1]) << 8) + (uint32(number[2]) << 16) // nolint: gomnd
} }
+13 -16
View File
@@ -10,9 +10,8 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
const ( const (
@@ -41,9 +40,8 @@ type wrapperMtprotoFrame struct {
writeSeqNo int32 writeSeqNo int32
} }
func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funlen, cyclop
buf := acquireMtprotoFrameBytesBuffer() buf := &bytes.Buffer{}
defer releaseMtprotoFrameBytesBuffer(buf)
sum := crc32.NewIEEE() sum := crc32.NewIEEE()
writer := io.MultiWriter(buf, sum) writer := io.MultiWriter(buf, sum)
@@ -52,7 +50,7 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
buf.Reset() buf.Reset()
sum.Reset() sum.Reset()
if _, err := io.CopyN(writer, w.parent, 4); err != nil { if _, err := io.CopyN(writer, w.parent, 4); err != nil { // nolint: gomnd
return nil, fmt.Errorf("cannot read frame padding: %w", err) return nil, fmt.Errorf("cannot read frame padding: %w", err)
} }
@@ -74,7 +72,7 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
buf.Reset() buf.Reset()
if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil { if _, err := io.CopyN(writer, w.parent, int64(messageLength)-4-4); err != nil { // nolint: gomnd
return nil, fmt.Errorf("cannot read the message frame: %w", err) return nil, fmt.Errorf("cannot read the message frame: %w", err)
} }
@@ -86,11 +84,11 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo) return nil, fmt.Errorf("unexpected sequence number %d (wait for %d)", seqNo, w.readSeqNo)
} }
data, _ := ioutil.ReadAll(buf) // nolint: gosec data, _ := ioutil.ReadAll(buf)
buf.Reset() buf.Reset()
// write to buf, not to writer. This is because we are going to fetch // write to buf, not to writer. This is because we are going to fetch
// crc32 checksum. // crc32 checksum.
if _, err := io.CopyN(buf, w.parent, 4); err != nil { if _, err := io.CopyN(buf, w.parent, 4); err != nil { // nolint: gomnd
return nil, fmt.Errorf("cannot read checksum: %w", err) return nil, fmt.Errorf("cannot read checksum: %w", err)
} }
@@ -111,19 +109,18 @@ func (w *wrapperMtprotoFrame) Read() (conntypes.Packet, error) { // nolint: funl
} }
func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error { func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error {
messageLength := 4 + 4 + len(p) + 4 messageLength := 4 + 4 + len(p) + 4 // nolint: gomnd
paddingLength := (aes.BlockSize - messageLength%aes.BlockSize) % aes.BlockSize paddingLength := (aes.BlockSize - messageLength%aes.BlockSize) % aes.BlockSize
buf := acquireMtprotoFrameBytesBuffer() buf := &bytes.Buffer{}
defer releaseMtprotoFrameBytesBuffer(buf)
binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck binary.Write(buf, binary.LittleEndian, uint32(messageLength)) // nolint: errcheck
binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck binary.Write(buf, binary.LittleEndian, w.writeSeqNo) // nolint: errcheck
buf.Write(p) buf.Write(p)
checksum := crc32.ChecksumIEEE(buf.Bytes()) checksum := crc32.ChecksumIEEE(buf.Bytes())
binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck binary.Write(buf, binary.LittleEndian, checksum) // nolint: errcheck
buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) buf.Write(bytes.Repeat(mtprotoFramePadding, paddingLength/4)) // nolint: gomnd
w.logger.Debugw("Write MTProto frame", w.logger.Debugw("Write MTProto frame",
"length", len(p), "length", len(p),
@@ -135,11 +132,11 @@ func (w *wrapperMtprotoFrame) Write(p conntypes.Packet) error {
_, err := w.parent.Write(buf.Bytes()) _, err := w.parent.Write(buf.Bytes())
return err return err // nolint: wrapcheck
} }
func (w *wrapperMtprotoFrame) Close() error { func (w *wrapperMtprotoFrame) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperMtprotoFrame) Conn() net.Conn { func (w *wrapperMtprotoFrame) Conn() net.Conn {
-23
View File
@@ -1,23 +0,0 @@
package packet
import (
"bytes"
"sync"
)
var (
poolMtprotoFrameBytesBuffer = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
)
func acquireMtprotoFrameBytesBuffer() *bytes.Buffer {
return poolMtprotoFrameBytesBuffer.Get().(*bytes.Buffer)
}
func releaseMtprotoFrameBytesBuffer(buf *bytes.Buffer) {
buf.Reset()
poolMtprotoFrameBytesBuffer.Put(buf)
}
+6 -9
View File
@@ -6,10 +6,9 @@ import (
"io" "io"
"net" "net"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
"go.uber.org/zap"
) )
const ( const (
@@ -40,9 +39,9 @@ func (w *wrapperClientAbridged) Read(acks *conntypes.ConnectionAcks) (conntypes.
} }
if msgLength == clientAbridgedSmallPacketLength { if msgLength == clientAbridgedSmallPacketLength {
buf.Grow(3) buf.Grow(3) // nolint: gomnd
if _, err := io.CopyN(&buf, w.parent, 3); err != nil { if _, err := io.CopyN(&buf, w.parent, 3); err != nil { // nolint: gomnd
return nil, fmt.Errorf("cannot read correct message length: %w", err) return nil, fmt.Errorf("cannot read correct message length: %w", err)
} }
@@ -76,7 +75,7 @@ func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.C
return nil return nil
} }
packetLength := len(packet) / 4 packetLength := len(packet) / 4 // nolint: gomnd
switch { switch {
case packetLength < clientAbridgedSmallPacketLength: case packetLength < clientAbridgedSmallPacketLength:
@@ -88,9 +87,7 @@ func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.C
return nil return nil
case packetLength < clientAbridgedLargePacketLength: case packetLength < clientAbridgedLargePacketLength:
length24 := utils.ToUint24(uint32(packetLength)) length24 := utils.ToUint24(uint32(packetLength))
buf := bytes.Buffer{}
buf := acquireClientBytesBuffer()
defer releaseClientBytesBuffer(buf)
buf.WriteByte(byte(clientAbridgedSmallPacketLength)) buf.WriteByte(byte(clientAbridgedSmallPacketLength))
buf.Write(length24[:]) buf.Write(length24[:])
@@ -107,7 +104,7 @@ func (w *wrapperClientAbridged) Write(packet conntypes.Packet, acks *conntypes.C
} }
func (w *wrapperClientAbridged) Close() error { func (w *wrapperClientAbridged) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperClientAbridged) Conn() net.Conn { func (w *wrapperClientAbridged) Conn() net.Conn {
+4 -5
View File
@@ -7,9 +7,8 @@ import (
"io" "io"
"net" "net"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
const clientIntermediateQuickAckLength = 0x80000000 const clientIntermediateQuickAckLength = 0x80000000
@@ -21,9 +20,9 @@ type wrapperClientIntermediate struct {
func (w *wrapperClientIntermediate) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { func (w *wrapperClientIntermediate) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
buf := bytes.Buffer{} buf := bytes.Buffer{}
buf.Grow(4) buf.Grow(4) // nolint: gomnd
if _, err := io.CopyN(&buf, w.parent, 4); err != nil { if _, err := io.CopyN(&buf, w.parent, 4); err != nil { // nolint: gomnd
return nil, fmt.Errorf("cannot read message length: %w", err) return nil, fmt.Errorf("cannot read message length: %w", err)
} }
@@ -64,7 +63,7 @@ func (w *wrapperClientIntermediate) Write(packet conntypes.Packet, acks *conntyp
} }
func (w *wrapperClientIntermediate) Close() error { func (w *wrapperClientIntermediate) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperClientIntermediate) Conn() net.Conn { func (w *wrapperClientIntermediate) Conn() net.Conn {
@@ -1,13 +1,13 @@
package packetack package packetack
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/rand" "math/rand"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type wrapperClientIntermediateSecure struct { type wrapperClientIntermediateSecure struct {
@@ -20,7 +20,7 @@ func (w *wrapperClientIntermediateSecure) Read(acks *conntypes.ConnectionAcks) (
return nil, err return nil, err
} }
length := len(data) - (len(data) % 4) length := len(data) - (len(data) % 4) // nolint: gomnd
return data[:length], nil return data[:length], nil
} }
@@ -34,10 +34,9 @@ func (w *wrapperClientIntermediateSecure) Write(packet conntypes.Packet, acks *c
return nil return nil
} }
buf := acquireClientBytesBuffer() buf := &bytes.Buffer{}
defer releaseClientBytesBuffer(buf) paddingLength := rand.Intn(4) // nolint: gosec, gomnd
paddingLength := rand.Intn(4)
buf.Grow(4 + len(packet) + paddingLength) buf.Grow(4 + len(packet) + paddingLength)
binary.Write(buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck binary.Write(buf, binary.LittleEndian, uint32(len(packet)+paddingLength)) // nolint: errcheck
-23
View File
@@ -1,23 +0,0 @@
package packetack
import (
"bytes"
"sync"
)
var (
poolClientBytesBuffer = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
)
func acquireClientBytesBuffer() *bytes.Buffer {
return poolClientBytesBuffer.Get().(*bytes.Buffer)
}
func releaseClientBytesBuffer(buf *bytes.Buffer) {
buf.Reset()
poolClientBytesBuffer.Put(buf)
}
+4 -3
View File
@@ -42,11 +42,11 @@ func (w *wrapperProxy) Write(packet conntypes.Packet, acks *conntypes.Connection
buf.Write(rpc.ProxyRequestProxyTag) buf.Write(rpc.ProxyRequestProxyTag)
buf.WriteByte(byte(len(config.C.AdTag))) buf.WriteByte(byte(len(config.C.AdTag)))
buf.Write(config.C.AdTag) buf.Write(config.C.AdTag)
buf.Write(make([]byte, (4-buf.Len()%4)%4)) buf.Write(make([]byte, (4-buf.Len()%4)%4)) // nolint: gomnd
buf.Grow(len(packet)) buf.Grow(len(packet))
buf.Write(packet) buf.Write(packet)
return w.proxy.Write(buf.Bytes()) return w.proxy.Write(buf.Bytes()) // nolint: wrapcheck
} }
func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) { func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, error) {
@@ -64,6 +64,7 @@ func (w *wrapperProxy) Read(acks *conntypes.ConnectionAcks) (conntypes.Packet, e
func (w *wrapperProxy) Close() error { func (w *wrapperProxy) Close() error {
w.proxy.Close() w.proxy.Close()
return nil return nil
} }
@@ -77,7 +78,7 @@ func NewProxy(request *protocol.TelegramRequest) (conntypes.PacketAckReadWriteCl
flags |= rpc.ProxyRequestFlagsIntermediate flags |= rpc.ProxyRequestFlagsIntermediate
case conntypes.ConnectionTypeSecure: case conntypes.ConnectionTypeSecure:
flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad flags |= rpc.ProxyRequestFlagsIntermediate | rpc.ProxyRequestFlagsPad
default: case conntypes.ConnectionTypeUnknown:
panic("unknown connection type") panic("unknown connection type")
} }
+3 -3
View File
@@ -20,7 +20,7 @@ func (w *wrapperPing) Read(p []byte) (int, error) {
} }
} }
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperPing) Write(p []byte) (int, error) { func (w *wrapperPing) Write(p []byte) (int, error) {
@@ -32,11 +32,11 @@ func (w *wrapperPing) Write(p []byte) (int, error) {
} }
} }
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperPing) Close() error { func (w *wrapperPing) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func NewPing(ctx context.Context, parent io.ReadWriteCloser, channelPing chan<- struct{}) io.ReadWriteCloser { func NewPing(ctx context.Context, parent io.ReadWriteCloser, channelPing chan<- struct{}) io.ReadWriteCloser {
+6 -6
View File
@@ -7,10 +7,9 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/utils" "github.com/9seconds/mtg/utils"
"go.uber.org/zap"
) )
type wrapperBlockCipher struct { type wrapperBlockCipher struct {
@@ -27,7 +26,7 @@ func (w *wrapperBlockCipher) Write(p []byte) (int, error) {
return 0, err return 0, err
} }
return w.parent.Write(encrypted) return w.parent.Write(encrypted) // nolint: wrapcheck
} }
func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
@@ -36,7 +35,7 @@ func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int,
return 0, err return 0, err
} }
return w.parent.WriteTimeout(encrypted, timeout) return w.parent.WriteTimeout(encrypted, timeout) // nolint: wrapcheck
} }
func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) { func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) {
@@ -51,7 +50,7 @@ func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) {
} }
func (w *wrapperBlockCipher) Close() error { func (w *wrapperBlockCipher) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperBlockCipher) Conn() net.Conn { func (w *wrapperBlockCipher) Conn() net.Conn {
@@ -71,7 +70,8 @@ func (w *wrapperBlockCipher) RemoteAddr() *net.TCPAddr {
} }
func newBlockCipher(parent conntypes.StreamReadWriteCloser, func newBlockCipher(parent conntypes.StreamReadWriteCloser,
encryptor, decryptor cipher.BlockMode) conntypes.StreamReadWriteCloser { encryptor, decryptor cipher.BlockMode,
) conntypes.StreamReadWriteCloser {
cipher := &wrapperBlockCipher{ cipher := &wrapperBlockCipher{
parent: parent, parent: parent,
encryptor: encryptor, encryptor: encryptor,
+1 -1
View File
@@ -33,7 +33,7 @@ func (b *bufferedReader) ReadTimeout(p []byte, _ time.Duration) (int, error) {
func (b *bufferedReader) flush(p []byte) (int, error) { func (b *bufferedReader) flush(p []byte) (int, error) {
if b.buf.Len() > len(p) { if b.buf.Len() > len(p) {
return b.buf.Read(p) return b.buf.Read(p) // nolint: wrapcheck
} }
sizeToReturn := b.buf.Len() sizeToReturn := b.buf.Len()
+13 -10
View File
@@ -5,10 +5,9 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/config" "github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type connPurpose uint8 type connPurpose uint8
@@ -29,6 +28,7 @@ type wrapperConn struct {
func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperConn) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
if err := w.parent.SetWriteDeadline(time.Now().Add(timeout)); err != nil { if err := w.parent.SetWriteDeadline(time.Now().Add(timeout)); err != nil {
w.Close() w.Close()
return 0, fmt.Errorf("cannot set write deadline to the socket: %w", err) return 0, fmt.Errorf("cannot set write deadline to the socket: %w", err)
} }
@@ -40,15 +40,16 @@ func (w *wrapperConn) Write(p []byte) (int, error) {
w.logger.Debugw("write to stream", "bytes", n, "error", err) w.logger.Debugw("write to stream", "bytes", n, "error", err)
if err != nil { if err != nil {
w.Close() // nolint: gosec w.Close()
} }
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperConn) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
if err := w.parent.SetReadDeadline(time.Now().Add(timeout)); err != nil { if err := w.parent.SetReadDeadline(time.Now().Add(timeout)); err != nil {
w.Close() w.Close()
return 0, fmt.Errorf("cannot set read deadline to the socket: %w", err) return 0, fmt.Errorf("cannot set read deadline to the socket: %w", err)
} }
@@ -63,12 +64,13 @@ func (w *wrapperConn) Read(p []byte) (int, error) {
w.Close() w.Close()
} }
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperConn) Close() error { func (w *wrapperConn) Close() error {
w.logger.Debugw("Close connection") w.logger.Debugw("Close connection")
return w.parent.Close()
return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperConn) Conn() net.Conn { func (w *wrapperConn) Conn() net.Conn {
@@ -89,10 +91,11 @@ func (w *wrapperConn) RemoteAddr() *net.TCPAddr {
func newConn(parent net.Conn, func newConn(parent net.Conn,
connID conntypes.ConnID, connID conntypes.ConnID,
purpose connPurpose) conntypes.StreamReadWriteCloser { purpose connPurpose,
localAddr := *parent.LocalAddr().(*net.TCPAddr) ) conntypes.StreamReadWriteCloser {
localAddr := *parent.LocalAddr().(*net.TCPAddr) // nolint: forcetypeassert
if parent.RemoteAddr().(*net.TCPAddr).IP.To4() != nil { if parent.RemoteAddr().(*net.TCPAddr).IP.To4() != nil { // nolint: forcetypeassert
if config.C.PublicIPv4.IP != nil { if config.C.PublicIPv4.IP != nil {
localAddr.IP = config.C.PublicIPv4.IP localAddr.IP = config.C.PublicIPv4.IP
} }
@@ -115,7 +118,7 @@ func newConn(parent net.Conn,
parent: parent, parent: parent,
connID: connID, connID: connID,
logger: logger, logger: logger,
remoteAddr: parent.RemoteAddr().(*net.TCPAddr), remoteAddr: parent.RemoteAddr().(*net.TCPAddr), // nolint: forcetypeassert
localAddr: &localAddr, localAddr: &localAddr,
} }
} }
+13 -8
View File
@@ -6,9 +6,8 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type wrapperCtx struct { type wrapperCtx struct {
@@ -21,9 +20,10 @@ func (w *wrapperCtx) WriteTimeout(p []byte, timeout time.Duration) (int, error)
select { select {
case <-w.ctx.Done(): case <-w.ctx.Done():
w.Close() w.Close()
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
default: default:
return w.parent.WriteTimeout(p, timeout) return w.parent.WriteTimeout(p, timeout) // nolint: wrapcheck
} }
} }
@@ -31,9 +31,10 @@ func (w *wrapperCtx) Write(p []byte) (int, error) {
select { select {
case <-w.ctx.Done(): case <-w.ctx.Done():
w.Close() w.Close()
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
default: default:
return w.parent.Write(p) return w.parent.Write(p) // nolint: wrapcheck
} }
} }
@@ -41,9 +42,10 @@ func (w *wrapperCtx) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
select { select {
case <-w.ctx.Done(): case <-w.ctx.Done():
w.Close() w.Close()
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
default: default:
return w.parent.ReadTimeout(p, timeout) return w.parent.ReadTimeout(p, timeout) // nolint: wrapcheck
} }
} }
@@ -51,15 +53,17 @@ func (w *wrapperCtx) Read(p []byte) (int, error) {
select { select {
case <-w.ctx.Done(): case <-w.ctx.Done():
w.Close() w.Close()
return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err()) return 0, fmt.Errorf("cannot write because context was closed: %w", w.ctx.Err())
default: default:
return w.parent.Read(p) return w.parent.Read(p) // nolint: wrapcheck
} }
} }
func (w *wrapperCtx) Close() error { func (w *wrapperCtx) Close() error {
w.cancel() w.cancel()
return w.parent.Close()
return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperCtx) Conn() net.Conn { func (w *wrapperCtx) Conn() net.Conn {
@@ -80,7 +84,8 @@ func (w *wrapperCtx) RemoteAddr() *net.TCPAddr {
func NewCtx(ctx context.Context, func NewCtx(ctx context.Context,
cancel context.CancelFunc, cancel context.CancelFunc,
parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { parent conntypes.StreamReadWriteCloser,
) conntypes.StreamReadWriteCloser {
return &wrapperCtx{ return &wrapperCtx{
parent: parent, parent: parent,
ctx: ctx, ctx: ctx,
+10 -10
View File
@@ -7,10 +7,9 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/tlstypes" "github.com/9seconds/mtg/tlstypes"
"go.uber.org/zap"
) )
type wrapperFakeTLS struct { type wrapperFakeTLS struct {
@@ -21,7 +20,7 @@ type wrapperFakeTLS struct {
func (w *wrapperFakeTLS) Write(p []byte) (int, error) { func (w *wrapperFakeTLS) Write(p []byte) (int, error) {
return w.write(p, func(b []byte) (int, error) { return w.write(p, func(b []byte) (int, error) {
return w.parent.Write(b) return w.parent.Write(b) // nolint: wrapcheck
}) })
} }
@@ -31,21 +30,20 @@ func (w *wrapperFakeTLS) WriteTimeout(p []byte, timeout time.Duration) (int, err
return w.write(p, func(b []byte) (int, error) { return w.write(p, func(b []byte) (int, error) {
elapsed := time.Since(startTime) elapsed := time.Since(startTime)
if elapsed > timeout { if elapsed > timeout {
return w.parent.WriteTimeout(b, timeout-elapsed) return w.parent.WriteTimeout(b, timeout-elapsed) // nolint: wrapcheck
} }
return 0, errors.New("timeout") return 0, errors.New("timeout")
}) })
} }
func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) { func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
sum := 0 sum := 0
buf := bytes.Buffer{}
buf := acquireBytesBuffer()
defer releaseBytesBuffer(buf)
for _, v := range tlstypes.MakeRecords(p) { for _, v := range tlstypes.MakeRecords(p) {
buf.Reset() buf.Reset()
v.WriteBytes(buf) v.WriteBytes(&buf)
_, err := writeFunc(buf.Bytes()) _, err := writeFunc(buf.Bytes())
if err != nil { if err != nil {
@@ -75,7 +73,7 @@ func (w *wrapperFakeTLS) RemoteAddr() *net.TCPAddr {
} }
func (w *wrapperFakeTLS) Close() error { func (w *wrapperFakeTLS) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser {
@@ -87,7 +85,7 @@ func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWrit
for { for {
rec, err := tlstypes.ReadRecord(faketls.parent) rec, err := tlstypes.ReadRecord(faketls.parent)
if err != nil { if err != nil {
return nil, err return nil, err // nolint: wrapcheck
} }
switch rec.Type { switch rec.Type {
@@ -97,6 +95,8 @@ func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWrit
rec.Data.WriteBytes(buf) rec.Data.WriteBytes(buf)
return buf.Bytes(), nil return buf.Bytes(), nil
case tlstypes.RecordTypeHandshake:
return nil, errors.New("unsupported record type handshake")
default: default:
return nil, fmt.Errorf("unsupported record type %v", rec.Type) return nil, fmt.Errorf("unsupported record type %v", rec.Type)
} }
+22 -20
View File
@@ -1,10 +1,11 @@
package stream package stream
import ( import (
"bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/md5" // nolint: gosec "crypto/md5"
"crypto/sha1" // nolint: gosec "crypto/sha1"
"encoding/binary" "encoding/binary"
"net" "net"
@@ -25,7 +26,8 @@ var mtprotoEmptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
func NewMiddleProxyCipher(parent conntypes.StreamReadWriteCloser, func NewMiddleProxyCipher(parent conntypes.StreamReadWriteCloser,
req *rpc.NonceRequest, req *rpc.NonceRequest,
resp *rpc.NonceResponse, resp *rpc.NonceResponse,
secret []byte) conntypes.StreamReadWriteCloser { secret []byte,
) conntypes.StreamReadWriteCloser {
localAddr := parent.LocalAddr() localAddr := parent.LocalAddr()
remoteAddr := parent.RemoteAddr() remoteAddr := parent.RemoteAddr()
@@ -52,13 +54,13 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
req *rpc.NonceRequest, req *rpc.NonceRequest,
resp *rpc.NonceResponse, resp *rpc.NonceResponse,
client, remote *net.TCPAddr, client, remote *net.TCPAddr,
secret []byte) ([]byte, []byte) { secret []byte,
message := acquireBytesBuffer() ) ([]byte, []byte) {
defer releaseBytesBuffer(message) message := bytes.Buffer{}
message.Write(resp.Nonce) // nolint: gosec message.Write(resp.Nonce)
message.Write(req.Nonce) // nolint: gosec message.Write(req.Nonce)
message.Write(req.CryptoTS) // nolint: gosec message.Write(req.CryptoTS)
clientIPv4 := mtprotoEmptyIP[:] clientIPv4 := mtprotoEmptyIP[:]
serverIPv4 := mtprotoEmptyIP[:] serverIPv4 := mtprotoEmptyIP[:]
@@ -68,34 +70,34 @@ func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
serverIPv4 = utils.ReverseBytes(remote.IP.To4()) serverIPv4 = utils.ReverseBytes(remote.IP.To4())
} }
message.Write(serverIPv4) // nolint: gosec message.Write(serverIPv4)
var port [2]byte var port [2]byte
binary.LittleEndian.PutUint16(port[:], uint16(client.Port)) binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
message.Write(port[:]) // nolint: gosec message.Write(port[:])
switch purpose { switch purpose {
case mtprotoCipherPurposeClient: case mtprotoCipherPurposeClient:
message.WriteString("CLIENT") // nolint: gosec message.WriteString("CLIENT")
case mtprotoCipherPurposeServer: case mtprotoCipherPurposeServer:
message.WriteString("SERVER") // nolint: gosec message.WriteString("SERVER")
default: default:
panic("Unexpected cipher purpose") panic("Unexpected cipher purpose")
} }
message.Write(clientIPv4) // nolint: gosec message.Write(clientIPv4)
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port)) binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
message.Write(port[:]) // nolint: gosec message.Write(port[:])
message.Write(secret) // nolint: gosec message.Write(secret)
message.Write(resp.Nonce) // nolint: gosec message.Write(resp.Nonce)
if client.IP.To4() == nil { if client.IP.To4() == nil {
message.Write(client.IP.To16()) // nolint: gosec message.Write(client.IP.To16())
message.Write(remote.IP.To16()) // nolint: gosec message.Write(remote.IP.To16())
} }
message.Write(req.Nonce) // nolint: gosec message.Write(req.Nonce)
data := message.Bytes() data := message.Bytes()
md5sum := md5.Sum(data[1:]) // nolint: gas md5sum := md5.Sum(data[1:]) // nolint: gas
+10 -11
View File
@@ -1,14 +1,14 @@
package stream package stream
import ( import (
"bytes"
"crypto/cipher" "crypto/cipher"
"fmt" "fmt"
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type wrapperObfuscated2 struct { type wrapperObfuscated2 struct {
@@ -31,7 +31,7 @@ func (w *wrapperObfuscated2) ReadTimeout(p []byte, timeout time.Duration) (int,
func (w *wrapperObfuscated2) Read(p []byte) (int, error) { func (w *wrapperObfuscated2) Read(p []byte) (int, error) {
n, err := w.parent.Read(p) n, err := w.parent.Read(p)
if err != nil { if err != nil {
return n, err return n, err // nolint: wrapcheck
} }
w.decryptor.XORKeyStream(p, p[:n]) w.decryptor.XORKeyStream(p, p[:n])
@@ -40,8 +40,7 @@ func (w *wrapperObfuscated2) Read(p []byte) (int, error) {
} }
func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
buffer := acquireBytesBuffer() buffer := bytes.Buffer{}
defer releaseBytesBuffer(buffer)
buffer.Write(p) buffer.Write(p)
@@ -49,12 +48,11 @@ func (w *wrapperObfuscated2) WriteTimeout(p []byte, timeout time.Duration) (int,
w.encryptor.XORKeyStream(buf, buf) w.encryptor.XORKeyStream(buf, buf)
return w.parent.WriteTimeout(buf, timeout) return w.parent.WriteTimeout(buf, timeout) // nolint: wrapcheck
} }
func (w *wrapperObfuscated2) Write(p []byte) (int, error) { func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
buffer := acquireBytesBuffer() buffer := bytes.Buffer{}
defer releaseBytesBuffer(buffer)
buffer.Write(p) buffer.Write(p)
@@ -62,7 +60,7 @@ func (w *wrapperObfuscated2) Write(p []byte) (int, error) {
w.encryptor.XORKeyStream(buf, buf) w.encryptor.XORKeyStream(buf, buf)
return w.parent.Write(buf) return w.parent.Write(buf) // nolint: wrapcheck
} }
func (w *wrapperObfuscated2) Conn() net.Conn { func (w *wrapperObfuscated2) Conn() net.Conn {
@@ -82,11 +80,12 @@ func (w *wrapperObfuscated2) RemoteAddr() *net.TCPAddr {
} }
func (w *wrapperObfuscated2) Close() error { func (w *wrapperObfuscated2) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func NewObfuscated2(socket conntypes.StreamReadWriteCloser, func NewObfuscated2(socket conntypes.StreamReadWriteCloser,
encryptor, decryptor cipher.Stream) conntypes.StreamReadWriteCloser { encryptor, decryptor cipher.Stream,
) conntypes.StreamReadWriteCloser {
return &wrapperObfuscated2{ return &wrapperObfuscated2{
parent: socket, parent: socket,
encryptor: encryptor, encryptor: encryptor,
-23
View File
@@ -1,23 +0,0 @@
package stream
import (
"bytes"
"sync"
)
var (
poolBytesBuffer = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
)
func acquireBytesBuffer() *bytes.Buffer {
return poolBytesBuffer.Get().(*bytes.Buffer)
}
func releaseBytesBuffer(buf *bytes.Buffer) {
buf.Reset()
poolBytesBuffer.Put(buf)
}
+17 -38
View File
@@ -7,9 +7,8 @@ import (
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
type ReadWriteCloseRewinder interface { type ReadWriteCloseRewinder interface {
@@ -18,56 +17,32 @@ type ReadWriteCloseRewinder interface {
} }
type wrapperRewind struct { type wrapperRewind struct {
parent conntypes.StreamReadWriteCloser parent conntypes.StreamReadWriteCloser
buf bytes.Buffer activeReader io.Reader
mutex sync.Mutex buf bytes.Buffer
rewinded bool mutex sync.Mutex
} }
func (w *wrapperRewind) Write(p []byte) (int, error) { func (w *wrapperRewind) Write(p []byte) (int, error) {
return w.parent.Write(p) return w.parent.Write(p) // nolint: wrapcheck
} }
func (w *wrapperRewind) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperRewind) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
return w.parent.WriteTimeout(p, timeout) return w.parent.WriteTimeout(p, timeout) // nolint: wrapcheck
} }
func (w *wrapperRewind) Read(p []byte) (int, error) { func (w *wrapperRewind) Read(p []byte) (int, error) {
w.mutex.Lock() w.mutex.Lock()
defer w.mutex.Unlock() defer w.mutex.Unlock()
if w.rewinded { return w.activeReader.Read(p) // nolint: wrapcheck
if n, err := w.buf.Read(p); err != io.EOF {
return n, err
}
}
n, err := w.parent.Read(p)
if !w.rewinded {
w.buf.Write(p[:n])
}
return n, err
} }
func (w *wrapperRewind) ReadTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperRewind) ReadTimeout(p []byte, _ time.Duration) (int, error) {
w.mutex.Lock() w.mutex.Lock()
defer w.mutex.Unlock() defer w.mutex.Unlock()
if w.rewinded { return w.activeReader.Read(p) // nolint: wrapcheck
if n, err := w.buf.Read(p); err != io.EOF {
return n, err
}
}
n, err := w.parent.ReadTimeout(p, timeout)
if !w.rewinded {
w.buf.Write(p[:n])
}
return n, err
} }
func (w *wrapperRewind) Conn() net.Conn { func (w *wrapperRewind) Conn() net.Conn {
@@ -88,17 +63,21 @@ func (w *wrapperRewind) RemoteAddr() *net.TCPAddr {
func (w *wrapperRewind) Close() error { func (w *wrapperRewind) Close() error {
w.buf.Reset() w.buf.Reset()
return w.parent.Close()
return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperRewind) Rewind() { func (w *wrapperRewind) Rewind() {
w.mutex.Lock() w.mutex.Lock()
w.rewinded = true w.activeReader = io.MultiReader(&w.buf, w.parent)
w.mutex.Unlock() w.mutex.Unlock()
} }
func NewRewind(parent conntypes.StreamReadWriteCloser) ReadWriteCloseRewinder { func NewRewind(parent conntypes.StreamReadWriteCloser) ReadWriteCloseRewinder {
return &wrapperRewind{ rv := &wrapperRewind{
parent: parent, parent: parent,
} }
rv.activeReader = io.TeeReader(parent, &rv.buf)
return rv
} }
+6 -7
View File
@@ -5,10 +5,9 @@ import (
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/stats" "github.com/9seconds/mtg/stats"
"go.uber.org/zap"
) )
type wrapperTelegramStats struct { type wrapperTelegramStats struct {
@@ -18,19 +17,19 @@ type wrapperTelegramStats struct {
} }
func (w *wrapperTelegramStats) Write(p []byte) (int, error) { func (w *wrapperTelegramStats) Write(p []byte) (int, error) {
return w.parent.Write(p) return w.parent.Write(p) // nolint: wrapcheck
} }
func (w *wrapperTelegramStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTelegramStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
return w.parent.WriteTimeout(p, timeout) return w.parent.WriteTimeout(p, timeout) // nolint: wrapcheck
} }
func (w *wrapperTelegramStats) Read(p []byte) (int, error) { func (w *wrapperTelegramStats) Read(p []byte) (int, error) {
return w.parent.Read(p) return w.parent.Read(p) // nolint: wrapcheck
} }
func (w *wrapperTelegramStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTelegramStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
return w.parent.ReadTimeout(p, timeout) return w.parent.ReadTimeout(p, timeout) // nolint: wrapcheck
} }
func (w *wrapperTelegramStats) Conn() net.Conn { func (w *wrapperTelegramStats) Conn() net.Conn {
@@ -57,7 +56,7 @@ func (w *wrapperTelegramStats) Close() error {
stats.Stats.TelegramDisconnected(w.dc, w.RemoteAddr()) stats.Stats.TelegramDisconnected(w.dc, w.RemoteAddr())
}) })
return err return err // nolint: wrapcheck
} }
func NewTelegramStats(dc conntypes.DC, parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { func NewTelegramStats(dc conntypes.DC, parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser {
+6 -7
View File
@@ -4,10 +4,9 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/stats" "github.com/9seconds/mtg/stats"
"go.uber.org/zap"
) )
type wrapperTrafficStats struct { type wrapperTrafficStats struct {
@@ -18,28 +17,28 @@ func (w *wrapperTrafficStats) Write(p []byte) (int, error) {
n, err := w.parent.Write(p) n, err := w.parent.Write(p)
stats.Stats.EgressTraffic(n) stats.Stats.EgressTraffic(n)
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperTrafficStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTrafficStats) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
n, err := w.parent.WriteTimeout(p, timeout) n, err := w.parent.WriteTimeout(p, timeout)
stats.Stats.EgressTraffic(n) stats.Stats.EgressTraffic(n)
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperTrafficStats) Read(p []byte) (int, error) { func (w *wrapperTrafficStats) Read(p []byte) (int, error) {
n, err := w.parent.Read(p) n, err := w.parent.Read(p)
stats.Stats.IngressTraffic(n) stats.Stats.IngressTraffic(n)
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperTrafficStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTrafficStats) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
n, err := w.parent.ReadTimeout(p, timeout) n, err := w.parent.ReadTimeout(p, timeout)
stats.Stats.IngressTraffic(n) stats.Stats.IngressTraffic(n)
return n, err return n, err // nolint: wrapcheck
} }
func (w *wrapperTrafficStats) Conn() net.Conn { func (w *wrapperTrafficStats) Conn() net.Conn {
@@ -59,7 +58,7 @@ func (w *wrapperTrafficStats) RemoteAddr() *net.TCPAddr {
} }
func (w *wrapperTrafficStats) Close() error { func (w *wrapperTrafficStats) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func NewTrafficStats(parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser { func NewTrafficStats(parent conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser {
+6 -7
View File
@@ -4,9 +4,8 @@ import (
"net" "net"
"time" "time"
"go.uber.org/zap"
"github.com/9seconds/mtg/conntypes" "github.com/9seconds/mtg/conntypes"
"go.uber.org/zap"
) )
const ( const (
@@ -19,23 +18,23 @@ type wrapperTimeout struct {
} }
func (w *wrapperTimeout) WriteTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTimeout) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
return w.parent.WriteTimeout(p, timeout) return w.parent.WriteTimeout(p, timeout) // nolint: wrapcheck
} }
func (w *wrapperTimeout) Write(p []byte) (int, error) { func (w *wrapperTimeout) Write(p []byte) (int, error) {
return w.parent.WriteTimeout(p, timeoutWrite) return w.parent.WriteTimeout(p, timeoutWrite) // nolint: wrapcheck
} }
func (w *wrapperTimeout) ReadTimeout(p []byte, timeout time.Duration) (int, error) { func (w *wrapperTimeout) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
return w.parent.ReadTimeout(p, timeout) return w.parent.ReadTimeout(p, timeout) // nolint: wrapcheck
} }
func (w *wrapperTimeout) Read(p []byte) (int, error) { func (w *wrapperTimeout) Read(p []byte) (int, error) {
return w.parent.ReadTimeout(p, timeoutRead) return w.parent.ReadTimeout(p, timeoutRead) // nolint: wrapcheck
} }
func (w *wrapperTimeout) Close() error { func (w *wrapperTimeout) Close() error {
return w.parent.Close() return w.parent.Close() // nolint: wrapcheck
} }
func (w *wrapperTimeout) Conn() net.Conn { func (w *wrapperTimeout) Conn() net.Conn {