mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
Sync v2.7.0
This commit is contained in:
parent
b6e37914aa
commit
5690301129
95
CHANGELOG.md
95
CHANGELOG.md
@ -11,6 +11,98 @@ The format is **not** based on [Keep a Changelog][kec], since the project
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-2048 / Build 750
|
||||||
|
|
||||||
|
* The environment variables `RESEARCH_LOGS` and `RESEARCH_METRICS` have been
|
||||||
|
removed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-2022 / Build 746
|
||||||
|
|
||||||
|
* The property `block_page_redirect` of objects within `server_groups` array
|
||||||
|
has been removed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-1981 / Build 744
|
||||||
|
|
||||||
|
* The objects within `server_groups` array had a change in their
|
||||||
|
`block_page_redirect` configuration, it now supports arrays of IP addresses
|
||||||
|
in `ipv4` and `ipv6` fields.
|
||||||
|
|
||||||
|
* Profile's file cache version was incremented. In case of
|
||||||
|
`BlockingModeCustomIP` the `profile.blocking_mode` IPv4/IPv6 fields are now
|
||||||
|
arrays of IP addresses.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-2012 / Build 732
|
||||||
|
|
||||||
|
* The querylog now has a new field, `"rn"`, which is a 16-bit unsigned random
|
||||||
|
number. Field `"u"`, the unique request ID, is deprecated and may be
|
||||||
|
removed in the future.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-1879 / Build 729
|
||||||
|
|
||||||
|
* Profile's file cache version was incremented. The new field
|
||||||
|
`authentication` has been added to profile's device object.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-1934 / Build 728
|
||||||
|
|
||||||
|
* The object `filters` has new properties: `index_refresh_timeout`, and
|
||||||
|
`rule_list_refresh_timeout`. So replace this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filters:
|
||||||
|
# …
|
||||||
|
```
|
||||||
|
|
||||||
|
with this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filters:
|
||||||
|
# …
|
||||||
|
index_refresh_timeout: 1m
|
||||||
|
rule_list_refresh_timeout: 1m
|
||||||
|
```
|
||||||
|
|
||||||
|
* The objects `safe_browsing` and `adult_blocking` have a new property:
|
||||||
|
`refresh_timeout`. So replace this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
safe_browsing:
|
||||||
|
# …
|
||||||
|
# …
|
||||||
|
adult_blocking:
|
||||||
|
# …
|
||||||
|
```
|
||||||
|
|
||||||
|
with this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
safe_browsing:
|
||||||
|
# …
|
||||||
|
refresh_timeout: 1m
|
||||||
|
# …
|
||||||
|
adult_blocking:
|
||||||
|
# …
|
||||||
|
refresh_timeout: 1m
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## AGDNS-1954 / Build 726
|
||||||
|
|
||||||
|
* The object `web` has a new optional property, `general_blocking`. Its
|
||||||
|
format is the same as in `adult_blocking` and `safe_browsing`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## AGDNS-1954 / Build 719
|
## AGDNS-1954 / Build 719
|
||||||
|
|
||||||
* The objects within `server_groups` array have a new property
|
* The objects within `server_groups` array have a new property
|
||||||
@ -37,6 +129,9 @@ The format is **not** based on [Keep a Changelog][kec], since the project
|
|||||||
probability: 0.01
|
probability: 0.01
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> For `ipv4` and `ipv6` only one address is currently supported.
|
||||||
|
|
||||||
For server groups that do not require a block-page redirect, set:
|
For server groups that do not require a block-page redirect, set:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
6
Makefile
6
Makefile
@ -8,7 +8,7 @@
|
|||||||
# Makefile. Bump this number every time a significant change is made to
|
# Makefile. Bump this number every time a significant change is made to
|
||||||
# this Makefile.
|
# this Makefile.
|
||||||
#
|
#
|
||||||
# AdGuard-Project-Version: 4
|
# AdGuard-Project-Version: 5
|
||||||
|
|
||||||
# Don't name these macros "GO" etc., because GNU Make apparently makes
|
# Don't name these macros "GO" etc., because GNU Make apparently makes
|
||||||
# them exported environment variables with the literal value of
|
# them exported environment variables with the literal value of
|
||||||
@ -22,8 +22,8 @@ VERBOSE.MACRO = $${VERBOSE:-0}
|
|||||||
|
|
||||||
BRANCH = $$( git rev-parse --abbrev-ref HEAD )
|
BRANCH = $$( git rev-parse --abbrev-ref HEAD )
|
||||||
GOAMD64 = v1
|
GOAMD64 = v1
|
||||||
GOPROXY = https://goproxy.cn|https://proxy.golang.org|direct
|
GOPROXY = https://proxy.golang.org|direct
|
||||||
GOTOOLCHAIN = go1.21.8
|
GOTOOLCHAIN = go1.22.4
|
||||||
RACE = 0
|
RACE = 0
|
||||||
REVISION = $$( git rev-parse --short HEAD )
|
REVISION = $$( git rev-parse --short HEAD )
|
||||||
VERSION = 0
|
VERSION = 0
|
||||||
|
@ -196,33 +196,44 @@ web:
|
|||||||
certificates:
|
certificates:
|
||||||
- certificate: './test/cert.crt'
|
- certificate: './test/cert.crt'
|
||||||
key: './test/cert.key'
|
key: './test/cert.key'
|
||||||
# Optional safe browsing web server configuration. static_content is not
|
# Optional adult blocking web server configuration. static_content is not
|
||||||
# served on these addresses. The addresses should be the same as in the
|
# served on these addresses. The addresses should be the same as in the
|
||||||
# safe_browsing object.
|
# general_blocking and safe_browsing objects.
|
||||||
safe_browsing:
|
adult_blocking:
|
||||||
bind:
|
bind:
|
||||||
- address: '127.0.0.1:9081'
|
- address: '127.0.0.1:9081'
|
||||||
- address: '127.0.0.1:9444'
|
- address: '127.0.0.1:9444'
|
||||||
certificates:
|
certificates:
|
||||||
- certificate: './test/cert.crt'
|
- certificate: './test/cert.crt'
|
||||||
key: './test/cert.key'
|
key: './test/cert.key'
|
||||||
block_page: './test/block_page_sb.html'
|
block_page: './test/block_page_adult.html'
|
||||||
# Optional adult blocking web server configuration. static_content is not
|
# Optional general blocking web server configuration. static_content is not
|
||||||
# served on these addresses. The addresses should be the same as in the
|
# served on these addresses. The addresses should be the same as in the
|
||||||
# adult_blocking object.
|
# adult_blocking and safe_browsing objects.
|
||||||
adult_blocking:
|
general_blocking:
|
||||||
bind:
|
bind:
|
||||||
- address: '127.0.0.1:9082'
|
- address: '127.0.0.1:9082'
|
||||||
- address: '127.0.0.1:9445'
|
- address: '127.0.0.1:9445'
|
||||||
certificates:
|
certificates:
|
||||||
- certificate: './test/cert.crt'
|
- certificate: './test/cert.crt'
|
||||||
key: './test/cert.key'
|
key: './test/cert.key'
|
||||||
block_page: './test/block_page_adult.html'
|
block_page: './test/block_page_general.html'
|
||||||
|
# Optional safe browsing web server configuration. static_content is not
|
||||||
|
# served on these addresses. The addresses should be the same as in the
|
||||||
|
# general_blocking and safe_browsing objects.
|
||||||
|
safe_browsing:
|
||||||
|
bind:
|
||||||
|
- address: '127.0.0.1:9083'
|
||||||
|
- address: '127.0.0.1:9446'
|
||||||
|
certificates:
|
||||||
|
- certificate: './test/cert.crt'
|
||||||
|
key: './test/cert.key'
|
||||||
|
block_page: './test/block_page_sb.html'
|
||||||
# Listen addresses for the web service in addition to the ones in the
|
# Listen addresses for the web service in addition to the ones in the
|
||||||
# DNS-over-HTTPS handlers.
|
# DNS-over-HTTPS handlers.
|
||||||
non_doh_bind:
|
non_doh_bind:
|
||||||
- address: '127.0.0.1:9083'
|
- address: '127.0.0.1:9084'
|
||||||
- address: '127.0.0.1:9446'
|
- address: '127.0.0.1:9447'
|
||||||
certificates:
|
certificates:
|
||||||
- certificate: './test/cert.crt'
|
- certificate: './test/cert.crt'
|
||||||
key: './test/cert.key'
|
key: './test/cert.key'
|
||||||
@ -253,6 +264,7 @@ safe_browsing:
|
|||||||
cache_size: 1024
|
cache_size: 1024
|
||||||
cache_ttl: 1h
|
cache_ttl: 1h
|
||||||
refresh_interval: 1h
|
refresh_interval: 1h
|
||||||
|
refresh_timeout: 1m
|
||||||
|
|
||||||
# AdGuard adult content blocking filter configuration.
|
# AdGuard adult content blocking filter configuration.
|
||||||
adult_blocking:
|
adult_blocking:
|
||||||
@ -260,8 +272,12 @@ adult_blocking:
|
|||||||
cache_size: 1024
|
cache_size: 1024
|
||||||
cache_ttl: 1h
|
cache_ttl: 1h
|
||||||
refresh_interval: 1h
|
refresh_interval: 1h
|
||||||
|
refresh_timeout: 1m
|
||||||
|
|
||||||
# Settings for rule-list-based filters.
|
# Settings for rule-list-based filters.
|
||||||
|
#
|
||||||
|
# TODO(a.garipov): Add the timeout for the blocked-service index refresh. It
|
||||||
|
# is currently hardcoded to 3 minutes.
|
||||||
filters:
|
filters:
|
||||||
# The TTL to set for responses to requests for filtered domains.
|
# The TTL to set for responses to requests for filtered domains.
|
||||||
response_ttl: 5m
|
response_ttl: 5m
|
||||||
@ -273,9 +289,17 @@ filters:
|
|||||||
# How often to update filters from the index. See the documentation for the
|
# How often to update filters from the index. See the documentation for the
|
||||||
# FILTER_INDEX_URL environment variable.
|
# FILTER_INDEX_URL environment variable.
|
||||||
refresh_interval: 1h
|
refresh_interval: 1h
|
||||||
# The timeout for the entire filter update operation. Be aware that each
|
# The timeout for the entire filter update operation. Note that filter
|
||||||
# individual refresh operation also has its own hardcoded 3m timeout.
|
# rule-list index and each filter rule-list update operations have their own
|
||||||
|
# timeouts, see index_refresh_timeout and rule_list_refresh_timeout.
|
||||||
refresh_timeout: 5m
|
refresh_timeout: 5m
|
||||||
|
# The timeout for the filter rule-list index update operation. See also
|
||||||
|
# refresh_timeout for the entire filter update operation.
|
||||||
|
index_refresh_timeout: 1m
|
||||||
|
# The timeout for the filter update operation of each rule-list, including
|
||||||
|
# the safe-search ones. See also refresh_timeout for the entire filter
|
||||||
|
# update operation.
|
||||||
|
rule_list_refresh_timeout: 1m
|
||||||
# MaxSize is the maximum size of the downloadable filtering rule-list.
|
# MaxSize is the maximum size of the downloadable filtering rule-list.
|
||||||
max_size: 256MB
|
max_size: 256MB
|
||||||
# Rule list cache.
|
# Rule list cache.
|
||||||
@ -351,38 +375,6 @@ server_groups:
|
|||||||
- name: 'adguard_dns_default'
|
- name: 'adguard_dns_default'
|
||||||
# This filtering_group is used for all anonymous clients.
|
# This filtering_group is used for all anonymous clients.
|
||||||
filtering_group: 'default'
|
filtering_group: 'default'
|
||||||
# Settings for redirection to a block page.
|
|
||||||
block_page_redirect:
|
|
||||||
# If enabled is false, other fields can be skipped.
|
|
||||||
enabled: true
|
|
||||||
# Addresses to use for A queries. If enabled is true, ipv4, ipv6, or
|
|
||||||
# both must be filled.
|
|
||||||
ipv4:
|
|
||||||
- address: '127.0.0.1'
|
|
||||||
- address: '127.0.0.2'
|
|
||||||
# Addresses to use for AAAA queries. If enabled is true, ipv4, ipv6, or
|
|
||||||
# both must be filled.
|
|
||||||
ipv6:
|
|
||||||
- address: '::1'
|
|
||||||
- address: '::2'
|
|
||||||
# Request parameters based on which the block page is always shown. For
|
|
||||||
# requests matching these parameters, both skip and probability are
|
|
||||||
# ignored.
|
|
||||||
apply:
|
|
||||||
client:
|
|
||||||
- address: '192.168.0.0/16'
|
|
||||||
- address: '1.2.3.4'
|
|
||||||
# Request parameters based on which the block page is never shown. For
|
|
||||||
# requests matching these parameters, probability is ignored.
|
|
||||||
skip:
|
|
||||||
client:
|
|
||||||
- address: '1.2.0.0/16'
|
|
||||||
- address: '5.6.7.8'
|
|
||||||
question:
|
|
||||||
- domain: 'do-not-show-block.site.example'
|
|
||||||
# The probability of responding with the block page IPs based on remote
|
|
||||||
# address. Must be between 0.0 and 1.0.
|
|
||||||
probability: 0.01
|
|
||||||
ddr:
|
ddr:
|
||||||
enabled: true
|
enabled: true
|
||||||
# Device ID domain name suffix to DDR record template mapping. Keep in
|
# Device ID domain name suffix to DDR record template mapping. Keep in
|
||||||
|
@ -28,7 +28,6 @@ configuration file with comments.
|
|||||||
* [Filtering groups](#filtering_groups)
|
* [Filtering groups](#filtering_groups)
|
||||||
* [Network interface listeners](#interface_listeners)
|
* [Network interface listeners](#interface_listeners)
|
||||||
* [Server groups](#server_groups)
|
* [Server groups](#server_groups)
|
||||||
* [Block-page redirecting](#server_groups-*-block_page_redirect)
|
|
||||||
* [DDR](#server_groups-*-ddr)
|
* [DDR](#server_groups-*-ddr)
|
||||||
* [TLS](#server_groups-*-tls)
|
* [TLS](#server_groups-*-tls)
|
||||||
* [Servers](#server_groups-*-servers-*)
|
* [Servers](#server_groups-*-servers-*)
|
||||||
@ -609,9 +608,9 @@ The optional `web` object has the following properties:
|
|||||||
```
|
```
|
||||||
|
|
||||||
* <a href="#web-safe_browsing" id="web-safe_browsing" name="web-safe_browsing">`safe_browsing`</a>:
|
* <a href="#web-safe_browsing" id="web-safe_browsing" name="web-safe_browsing">`safe_browsing`</a>:
|
||||||
The optional safe browsing web server configurations. Every request is
|
The optional safe browsing block-page web server configurations. Every
|
||||||
responded with the content from the file to which the `block_page` property
|
request is responded with the content from the file to which the
|
||||||
points.
|
`block_page` property points.
|
||||||
|
|
||||||
See the [full description of this API][http-block-pages] on the HTTP API
|
See the [full description of this API][http-block-pages] on the HTTP API
|
||||||
page.
|
page.
|
||||||
@ -639,10 +638,15 @@ The optional `web` object has the following properties:
|
|||||||
```
|
```
|
||||||
|
|
||||||
* <a href="#web-adult_blocking" id="web-adult_blocking" name="web-adult_blocking">`adult_blocking`</a>:
|
* <a href="#web-adult_blocking" id="web-adult_blocking" name="web-adult_blocking">`adult_blocking`</a>:
|
||||||
The optional adult blocking web server configurations. The format of the
|
The optional adult block-page web server configuration. The format of the
|
||||||
values is the same as in the [`safe_browsing`](#web-safe_browsing) object
|
values is the same as in the [`safe_browsing`](#web-safe_browsing) object
|
||||||
above.
|
above.
|
||||||
|
|
||||||
|
* <a href="#web-general_blocking" id="web-general_blocking" name="web-general_blocking">`general_blocking`</a>:
|
||||||
|
The optional general block-page web server configuration. The format of
|
||||||
|
the values is the same as in the [`safe_browsing`](#web-safe_browsing)
|
||||||
|
object above.
|
||||||
|
|
||||||
* <a href="#web-non_doh_bind" id="web-non_doh_bind" name="web-non_doh_bind">`non_doh_bind`</a>:
|
* <a href="#web-non_doh_bind" id="web-non_doh_bind" name="web-non_doh_bind">`non_doh_bind`</a>:
|
||||||
The optional listen addresses and optional TLS configuration for the web
|
The optional listen addresses and optional TLS configuration for the web
|
||||||
service in addition to the ones in the DNS-over-HTTPS handlers. The
|
service in addition to the ones in the DNS-over-HTTPS handlers. The
|
||||||
@ -669,6 +673,9 @@ The optional `web` object has the following properties:
|
|||||||
|
|
||||||
Inside of the `headers` map, the header `Content-Type` is required.
|
Inside of the `headers` map, the header `Content-Type` is required.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Paths are case-sensitive.
|
||||||
|
|
||||||
**Property example:**
|
**Property example:**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -735,6 +742,11 @@ The `safe_browsing` object has the following properties:
|
|||||||
|
|
||||||
**Example:** `1m`.
|
**Example:** `1m`.
|
||||||
|
|
||||||
|
* <a href="#safe_browsing-refresh_timeout" id="safe_browsing-refresh_timeout" name="safe_browsing-refresh_timeout">`refresh_timeout`</a>:
|
||||||
|
The timeout for the update operation, as a human-readable duration.
|
||||||
|
|
||||||
|
**Example:** `1m`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## <a href="#adult_blocking" id="adult_blocking" name="adult_blocking">Adult-content blocking</a>
|
## <a href="#adult_blocking" id="adult_blocking" name="adult_blocking">Adult-content blocking</a>
|
||||||
@ -746,6 +758,9 @@ The `adult_blocking` object has the same properties as the
|
|||||||
|
|
||||||
## <a href="#filters" id="filters" name="filters">Filter Lists</a>
|
## <a href="#filters" id="filters" name="filters">Filter Lists</a>
|
||||||
|
|
||||||
|
**TODO(a.garipov):** Add the timeout for the blocked-service index refresh. It
|
||||||
|
is currently hardcoded to 3 minutes.
|
||||||
|
|
||||||
The `filters` object has the following properties:
|
The `filters` object has the following properties:
|
||||||
|
|
||||||
* <a href="#filters-response_ttl" id="filters-response_ttl" name="filters-response_ttl">`response_ttl`</a>:
|
* <a href="#filters-response_ttl" id="filters-response_ttl" name="filters-response_ttl">`response_ttl`</a>:
|
||||||
@ -777,11 +792,29 @@ The `filters` object has the following properties:
|
|||||||
|
|
||||||
* <a href="#filters-refresh_timeout" id="filters-refresh_timeout" name="filters-refresh_timeout">`refresh_timeout`</a>:
|
* <a href="#filters-refresh_timeout" id="filters-refresh_timeout" name="filters-refresh_timeout">`refresh_timeout`</a>:
|
||||||
The timeout for the *entire* filter update operation, as a human-readable
|
The timeout for the *entire* filter update operation, as a human-readable
|
||||||
duration. Be aware that each individual refresh operation also has its own
|
duration. Note that filter rule-list index and each filter rule-list
|
||||||
hardcoded 3m timeout.
|
update operations have their own timeouts, see
|
||||||
|
[`index_refresh_timeout`](#filters-index_refresh_timeout) and
|
||||||
|
[`rule_list_refresh_timeout`](#filters-rule_list_refresh_timeout).
|
||||||
|
|
||||||
**Example:** `5m`.
|
**Example:** `5m`.
|
||||||
|
|
||||||
|
* <a href="#filters-index_refresh_timeout" id="filters-index_refresh_timeout" name="filters-index_refresh_timeout">`index_refresh_timeout`</a>:
|
||||||
|
The timeout for the filter rule-list index update operation, as a
|
||||||
|
human-readable duration. See also
|
||||||
|
[`refresh_timeout`](#filters-refresh_timeout) for the entire filter update
|
||||||
|
operation.
|
||||||
|
|
||||||
|
**Example:** `1m`.
|
||||||
|
|
||||||
|
* <a href="#filters-rule_list_refresh_timeout" id="filters-rule_list_refresh_timeout" name="filters-rule_list_refresh_timeout">`rule_list_refresh_timeout`</a>:
|
||||||
|
The timeout for the filter update operation of each rule-list, including the
|
||||||
|
safe-search ones, as a human-readable duration. See also
|
||||||
|
[`refresh_timeout`](#filters-refresh_timeout) for the entire filter update
|
||||||
|
operation.
|
||||||
|
|
||||||
|
**Example:** `1m`.
|
||||||
|
|
||||||
* <a href="#filters-max_size" id="filters-max_size" name="filters-max_size">`max_size`</a>:
|
* <a href="#filters-max_size" id="filters-max_size" name="filters-max_size">`max_size`</a>:
|
||||||
The maximum size of the downloadable content for a rule-list in a
|
The maximum size of the downloadable content for a rule-list in a
|
||||||
human-readable format.
|
human-readable format.
|
||||||
@ -939,9 +972,6 @@ The items of the `server_groups` array have the following properties:
|
|||||||
|
|
||||||
**Example:** `default`.
|
**Example:** `default`.
|
||||||
|
|
||||||
* `block_page_redirect`: The block-page redirect configuration object. See
|
|
||||||
[below](#server_groups-*-block_page_redirect).
|
|
||||||
|
|
||||||
* `ddr`: The DDR configuration object. See [below](#server_groups-*-ddr).
|
* `ddr`: The DDR configuration object. See [below](#server_groups-*-ddr).
|
||||||
|
|
||||||
* `tls`: The TLS configuration object. See [below](#server_groups-*-tls).
|
* `tls`: The TLS configuration object. See [below](#server_groups-*-tls).
|
||||||
@ -956,69 +986,6 @@ The items of the `server_groups` array have the following properties:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <a href="#server_groups-*-block_page_redirect" id="server_groups-*-block_page_redirect" name="server_groups-*-block_page_redirect">Block-page redirecting</a>
|
|
||||||
|
|
||||||
The block-page redirect configuration object. If enabled, AdGuard DNS responds
|
|
||||||
with the configured IP addresses to “redirect” users to an informative block
|
|
||||||
page.
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-enabled" id="sg-*-bpr-enabled" name="sg-*-bpr-enabled">`enabled`</a>:
|
|
||||||
|
|
||||||
Shows if the block-page redirect is enabled. If `false`, the fields below
|
|
||||||
can be skipped.
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-ipv4" id="sg-*-bpr-ipv4" name="sg-*-bpr-ipv4">`ipv4`</a>:
|
|
||||||
|
|
||||||
Arrays of IPv4 addresses with which to respond to blocked `A` queries.
|
|
||||||
|
|
||||||
If `enabled` is true, `ipv4`, `ipv6`, or both must be filled.
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-ipv6" id="sg-*-bpr-ipv6" name="sg-*-bpr-ipv6">`ipv6`</a>:
|
|
||||||
|
|
||||||
Arrays of IPv6 addresses with which to respond to blocked `AAAA` queries.
|
|
||||||
|
|
||||||
If `enabled` is true, `ipv4`, `ipv6`, or both must be filled.
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-apply" id="sg-*-bpr-apply" name="sg-*-bpr-apply">`apply`</a>:
|
|
||||||
|
|
||||||
Request parameters based on which the block-page redirect is always
|
|
||||||
performed. For requests matching these parameters, both `skip` and
|
|
||||||
`probability` are
|
|
||||||
ignored.
|
|
||||||
|
|
||||||
**Property example:**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apply:
|
|
||||||
client:
|
|
||||||
- address: '192.168.0.0/16'
|
|
||||||
- address: '1.2.3.4'
|
|
||||||
```
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-skip" id="sg-*-bpr-skip" name="sg-*-bpr-skip">`skip`</a>:
|
|
||||||
|
|
||||||
Request parameters based on which the block-page redirect is never
|
|
||||||
performed. For requests matching these parameters, `probability` is
|
|
||||||
ignored.
|
|
||||||
|
|
||||||
**Property example:**
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
skip:
|
|
||||||
client:
|
|
||||||
- address: '1.2.0.0/16'
|
|
||||||
- address: '5.6.7.8'
|
|
||||||
question:
|
|
||||||
- domain: 'do-not-show-block.site.example'
|
|
||||||
```
|
|
||||||
|
|
||||||
* <a href="#sg-*-bpr-probability" id="sg-*-bpr-probability" name="sg-*-bpr-probability">`probability`</a>:
|
|
||||||
|
|
||||||
The probability of responding with the block page IPs based on remote
|
|
||||||
address. Must be between `0.0` and `1.0`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <a href="#server_groups-*-ddr" id="server_groups-*-ddr" name="server_groups-*-ddr">DDR</a>
|
### <a href="#server_groups-*-ddr" id="server_groups-*-ddr" name="server_groups-*-ddr">DDR</a>
|
||||||
|
|
||||||
The DDR configuration object. Many of these data duplicate data from objects in
|
The DDR configuration object. Many of these data duplicate data from objects in
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
Development is supported on Linux and macOS (aka Darwin) systems.
|
Development is supported on Linux and macOS (aka Darwin) systems.
|
||||||
|
|
||||||
1. Install Go 1.21 or later.
|
1. Install Go 1.22 or later.
|
||||||
|
|
||||||
1. Call `make init` to set up the Git pre-commit hook.
|
1. Call `make init` to set up the Git pre-commit hook.
|
||||||
|
|
||||||
@ -219,15 +219,15 @@ curl 'https://raw.githubusercontent.com/maxmind/MaxMind-DB/main/test-data/GeoIP2
|
|||||||
|
|
||||||
You'll need to supply the following:
|
You'll need to supply the following:
|
||||||
|
|
||||||
* [`ADULT_BLOCKING_URL`](#env-ADULT_BLOCKING_URL)
|
* [`ADULT_BLOCKING_URL`][env-ADULT_BLOCKING_URL]
|
||||||
* [`BILLSTAT_URL`](#env-BILLSTAT_URL)
|
* [`BILLSTAT_URL`][env-BILLSTAT_URL]
|
||||||
* [`CONSUL_ALLOWLIST_URL`](#env-CONSUL_ALLOWLIST_URL)
|
* [`CONSUL_ALLOWLIST_URL`][env-CONSUL_ALLOWLIST_URL]
|
||||||
* [`GENERAL_SAFE_SEARCH_URL`](#env-GENERAL_SAFE_SEARCH_URL)
|
* [`GENERAL_SAFE_SEARCH_URL`][env-GENERAL_SAFE_SEARCH_URL]
|
||||||
* [`LINKED_IP_TARGET_URL`](#env-LINKED_IP_TARGET_URL)
|
* [`LINKED_IP_TARGET_URL`][env-LINKED_IP_TARGET_URL]
|
||||||
* [`NEW_REG_DOMAINS_URL`](#env-NEW_REG_DOMAINS_URL)
|
* [`NEW_REG_DOMAINS_URL`][env-NEW_REG_DOMAINS_URL]
|
||||||
* [`PROFILES_URL`](#env-PROFILES_URL)
|
* [`PROFILES_URL`][env-PROFILES_URL]
|
||||||
* [`SAFE_BROWSING_URL`](#env-SAFE_BROWSING_URL)
|
* [`SAFE_BROWSING_URL`][env-SAFE_BROWSING_URL]
|
||||||
* [`YOUTUBE_SAFE_SEARCH_URL`](#env-YOUTUBE_SAFE_SEARCH_URL)
|
* [`YOUTUBE_SAFE_SEARCH_URL`][env-YOUTUBE_SAFE_SEARCH_URL]
|
||||||
|
|
||||||
See the [external HTTP API documentation][externalhttp].
|
See the [external HTTP API documentation][externalhttp].
|
||||||
|
|
||||||
@ -280,6 +280,16 @@ env \
|
|||||||
./AdGuardDNS
|
./AdGuardDNS
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[env-ADULT_BLOCKING_URL]: environment.md#ADULT_BLOCKING_URL
|
||||||
|
[env-BILLSTAT_URL]: environment.md#BILLSTAT_URL
|
||||||
|
[env-CONSUL_ALLOWLIST_URL]: environment.md#CONSUL_ALLOWLIST_URL
|
||||||
|
[env-GENERAL_SAFE_SEARCH_URL]: environment.md#GENERAL_SAFE_SEARCH_URL
|
||||||
|
[env-LINKED_IP_TARGET_URL]: environment.md#LINKED_IP_TARGET_URL
|
||||||
|
[env-NEW_REG_DOMAINS_URL]: environment.md#NEW_REG_DOMAINS_URL
|
||||||
|
[env-PROFILES_URL]: environment.md#PROFILES_URL
|
||||||
|
[env-SAFE_BROWSING_URL]: environment.md#SAFE_BROWSING_URL
|
||||||
|
[env-YOUTUBE_SAFE_SEARCH_URL]: environment.md#YOUTUBE_SAFE_SEARCH_URL
|
||||||
|
|
||||||
[externalhttp]: externalhttp.md
|
[externalhttp]: externalhttp.md
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,8 +26,6 @@ sensitive configuration. All other configuration is stored in the
|
|||||||
* [`PROFILES_ENABLED`](#PROFILES_ENABLED)
|
* [`PROFILES_ENABLED`](#PROFILES_ENABLED)
|
||||||
* [`PROFILES_URL`](#PROFILES_URL)
|
* [`PROFILES_URL`](#PROFILES_URL)
|
||||||
* [`QUERYLOG_PATH`](#QUERYLOG_PATH)
|
* [`QUERYLOG_PATH`](#QUERYLOG_PATH)
|
||||||
* [`RESEARCH_LOGS`](#RESEARCH_LOGS)
|
|
||||||
* [`RESEARCH_METRICS`](#RESEARCH_METRICS)
|
|
||||||
* [`RULESTAT_URL`](#RULESTAT_URL)
|
* [`RULESTAT_URL`](#RULESTAT_URL)
|
||||||
* [`SAFE_BROWSING_URL`](#SAFE_BROWSING_URL)
|
* [`SAFE_BROWSING_URL`](#SAFE_BROWSING_URL)
|
||||||
* [`SENTRY_DSN`](#SENTRY_DSN)
|
* [`SENTRY_DSN`](#SENTRY_DSN)
|
||||||
@ -264,25 +262,6 @@ The path to the file into which the query log is going to be written.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## <a href="#RESEARCH_METRICS" id="RESEARCH_METRICS" name="RESEARCH_METRICS">`RESEARCH_METRICS`</a>
|
|
||||||
|
|
||||||
If `1`, enable collection of a set of special prometheus metrics (prefix is
|
|
||||||
`dns_research`). If `0`, disable collection of those metrics.
|
|
||||||
|
|
||||||
**Default:** `0`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## <a href="#RESEARCH_LOGS" id="RESEARCH_LOGS" name="RESEARCH_LOGS">`RESEARCH_LOGS`</a>
|
|
||||||
|
|
||||||
If `1`, enable logging of additional info that may be required for research
|
|
||||||
purposes (prefix `research:`). The log will only be written when
|
|
||||||
`RESEARCH_METRICS` is also set to `1`. If `0`, disable logging of this info.
|
|
||||||
|
|
||||||
**Default:** `0`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## <a href="#RULESTAT_URL" id="RULESTAT_URL" name="RULESTAT_URL">`RULESTAT_URL`</a>
|
## <a href="#RULESTAT_URL" id="RULESTAT_URL" name="RULESTAT_URL">`RULESTAT_URL`</a>
|
||||||
|
|
||||||
The URL to send filtering rule list statistics to. If empty or unset, the
|
The URL to send filtering rule list statistics to. If empty or unset, the
|
||||||
|
@ -17,9 +17,9 @@ appropriately.
|
|||||||
|
|
||||||
## <a href="#block-pages" id="block-pages" name="block-pages">Block Pages</a>
|
## <a href="#block-pages" id="block-pages" name="block-pages">Block Pages</a>
|
||||||
|
|
||||||
The safe browsing and adult blocking servers. Every request is responded with
|
The safe-browsing, adult-blocking, and popup-blocking servers. Every request is
|
||||||
the content from the configured file, with the exception of `GET /favicon.ico`
|
responded with the content from the configured file, with the exception of `GET
|
||||||
and `GET /robots.txt` requests, which are handled separately:
|
/favicon.ico` and `GET /robots.txt` requests, which are handled separately:
|
||||||
|
|
||||||
* `GET /favicon.ico` requests are responded with a plain-text `404 Not Found`
|
* `GET /favicon.ico` requests are responded with a plain-text `404 Not Found`
|
||||||
response.
|
response.
|
||||||
|
@ -5,8 +5,8 @@ entries are designed to be concise and easily compressable. An example of the
|
|||||||
log output:
|
log output:
|
||||||
|
|
||||||
```jsonl
|
```jsonl
|
||||||
{"u":"ABCD","b":"prof1234","i":"dev1234","c":"RU","d":"US","n":"example.com.","l":"cdef5678","m":"||example.com^","t":1628590394000,"a":1234,"e":5,"q":1,"f":2,"s":0,"p":8,"r":0}
|
{"u":"ABCD","b":"prof1234","i":"dev1234","c":"RU","d":"US","n":"example.com.","l":"cdef5678","m":"||example.com^","t":1628590394000,"a":1234,"e":5,"q":1,"rn":1234,"f":2,"s":0,"p":8,"r":0}
|
||||||
{"u":"DEFG","b":"prof1234","i":"dev1234","c":"RU","d":"JP","n":"example.org.","l":"hijk9012","m":"||example.org^","t":1628590394100,"a":6789,"e":6,"q":1,"f":2,"s":0,"p":8,"r":0}
|
{"u":"DEFG","b":"prof1234","i":"dev1234","c":"RU","d":"JP","n":"example.org.","l":"hijk9012","m":"||example.org^","t":1628590394100,"a":6789,"e":6,"q":1,"rn":56789,"f":2,"s":0,"p":8,"r":0}
|
||||||
```
|
```
|
||||||
|
|
||||||
AdGuard DNS opens and closes the log file on each write to prevent issues with
|
AdGuard DNS opens and closes the log file on each write to prevent issues with
|
||||||
@ -24,6 +24,9 @@ rules to remember, which property means what. The properties are:
|
|||||||
* <a href="#properties-u" id="properties-u" name="properties-u">`u`</a>:
|
* <a href="#properties-u" id="properties-u" name="properties-u">`u`</a>:
|
||||||
The unique ID of the request. The short name `u` stands for “unique”.
|
The unique ID of the request. The short name `u` stands for “unique”.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> This field is deprecated and may be removed in the future.
|
||||||
|
|
||||||
**Example:** `"ABCD1234"`
|
**Example:** `"ABCD1234"`
|
||||||
|
|
||||||
* <a href="#properties-b" id="properties-b" name="properties-b">`b`</a>:
|
* <a href="#properties-b" id="properties-b" name="properties-b">`b`</a>:
|
||||||
@ -141,6 +144,12 @@ rules to remember, which property means what. The properties are:
|
|||||||
|
|
||||||
See [this Wikipedia list][wiki-dnsrr] for numeric values and their meanings.
|
See [this Wikipedia list][wiki-dnsrr] for numeric values and their meanings.
|
||||||
|
|
||||||
|
* <a href="#properties-rn" id="properties-rn" name="properties-rn">`rn`</a>:
|
||||||
|
A random 16-bit unsigned integer added to an entry for easier deduplication
|
||||||
|
when `"u"` is not used for that.
|
||||||
|
|
||||||
|
**Example:** `12345`
|
||||||
|
|
||||||
* <a href="#properties-f" id="properties-f" name="properties-f">`f`</a>:
|
* <a href="#properties-f" id="properties-f" name="properties-f">`f`</a>:
|
||||||
The action taken with this request. The short name `f` stands for
|
The action taken with this request. The short name `f` stands for
|
||||||
“filtering”. The possible values are:
|
“filtering”. The possible values are:
|
||||||
|
48
go.mod
48
go.mod
@ -1,13 +1,13 @@
|
|||||||
module github.com/AdguardTeam/AdGuardDNS
|
module github.com/AdguardTeam/AdGuardDNS
|
||||||
|
|
||||||
go 1.21.8
|
go 1.22.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-00010101000000-000000000000
|
github.com/AdguardTeam/AdGuardDNS/internal/dnsserver v0.0.0-00010101000000-000000000000
|
||||||
github.com/AdguardTeam/golibs v0.20.1
|
github.com/AdguardTeam/golibs v0.23.2
|
||||||
github.com/AdguardTeam/urlfilter v0.18.0
|
github.com/AdguardTeam/urlfilter v0.18.0
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b
|
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02
|
||||||
github.com/bluele/gcache v0.0.2
|
github.com/bluele/gcache v0.0.2
|
||||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
|
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
|
||||||
github.com/caarlos0/env/v7 v7.1.0
|
github.com/caarlos0/env/v7 v7.1.0
|
||||||
@ -16,17 +16,18 @@ require (
|
|||||||
github.com/miekg/dns v1.1.58
|
github.com/miekg/dns v1.1.58
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.19.0
|
||||||
github.com/prometheus/client_model v0.5.0
|
github.com/prometheus/client_model v0.6.1
|
||||||
github.com/prometheus/common v0.46.0
|
github.com/prometheus/common v0.52.3
|
||||||
github.com/quic-go/quic-go v0.41.0
|
github.com/quic-go/quic-go v0.42.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
golang.org/x/crypto v0.22.0
|
||||||
golang.org/x/net v0.21.0
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
|
||||||
golang.org/x/sys v0.17.0
|
golang.org/x/net v0.24.0
|
||||||
|
golang.org/x/sys v0.19.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
google.golang.org/grpc v1.61.1
|
google.golang.org/grpc v1.63.2
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.33.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,23 +36,22 @@ require (
|
|||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||||
github.com/ameshkov/dnsstamps v1.0.3 // indirect
|
github.com/ameshkov/dnsstamps v1.0.3 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
github.com/panjf2000/ants/v2 v2.9.1 // indirect
|
||||||
github.com/panjf2000/ants/v2 v2.9.0 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.13.0 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/crypto v0.19.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/mod v0.15.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/tools v0.18.0 // indirect
|
golang.org/x/tools v0.20.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
101
go.sum
101
go.sum
@ -1,17 +1,17 @@
|
|||||||
github.com/AdguardTeam/golibs v0.20.1 h1:ol8qLjWGZhU9paMMwN+OLWVTUigGsXa29iVTyd62VKY=
|
github.com/AdguardTeam/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
|
||||||
github.com/AdguardTeam/golibs v0.20.1/go.mod h1:bgcMgRviCKyU6mkrX+RtT/OsKPFzyppelfRsksMG3KU=
|
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
|
||||||
github.com/AdguardTeam/urlfilter v0.18.0 h1:ZZzwODC/ADpjJSODxySrrUnt/fvOCfGFaCW6j+wsGfQ=
|
github.com/AdguardTeam/urlfilter v0.18.0 h1:ZZzwODC/ADpjJSODxySrrUnt/fvOCfGFaCW6j+wsGfQ=
|
||||||
github.com/AdguardTeam/urlfilter v0.18.0/go.mod h1:IXxBwedLiZA2viyHkaFxY/8mjub0li2PXRg8a3d9Z1s=
|
github.com/AdguardTeam/urlfilter v0.18.0/go.mod h1:IXxBwedLiZA2viyHkaFxY/8mjub0li2PXRg8a3d9Z1s=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7 h1:aEitLIR8HcxVodZ79mgRcCiC0A0I5kZPBuWGFwwulAw=
|
github.com/ameshkov/dnscrypt/v2 v2.3.0 h1:pDXDF7eFa6Lw+04C0hoMh8kCAQM8NwUdFEllSP2zNLs=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7/go.mod h1:qPWhwz6FdSmuK7W4sMyvogrez4MWdtzosdqlr0Rg3ow=
|
github.com/ameshkov/dnscrypt/v2 v2.3.0/go.mod h1:N5hDwgx2cNb4Ay7AhvOSKst+eUiOZ/vbKRO9qMpQttE=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b h1:F3yMzKumBUQ6Fn0sYI1YQ16vQRucpZOfBQ9HXWl5+XI=
|
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02 h1:bXAPYSbdYbS5VTy92NIUbeDI1qyggi+JYh5op9IFlcQ=
|
||||||
github.com/axiomhq/hyperloglog v0.0.0-20240124082744-24bca3a5b39b/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
||||||
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/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||||
@ -20,8 +20,8 @@ github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXye
|
|||||||
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||||
github.com/caarlos0/env/v7 v7.1.0 h1:9lzTF5amyQeWHZzuZeKlCb5FWSUxpG1js43mhbY8ozg=
|
github.com/caarlos0/env/v7 v7.1.0 h1:9lzTF5amyQeWHZzuZeKlCb5FWSUxpG1js43mhbY8ozg=
|
||||||
github.com/caarlos0/env/v7 v7.1.0/go.mod h1:LPPWniDUq4JaO6Q41vtlyikhMknqymCLBw0eX4dcH1E=
|
github.com/caarlos0/env/v7 v7.1.0/go.mod h1:LPPWniDUq4JaO6Q41vtlyikhMknqymCLBw0eX4dcH1E=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
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=
|
||||||
@ -38,14 +38,12 @@ github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
|||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@ -56,14 +54,14 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ
|
|||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||||
github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo=
|
github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw=
|
||||||
github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
github.com/panjf2000/ants/v2 v2.9.1/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||||
@ -74,18 +72,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
||||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
|
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
|
||||||
@ -99,8 +97,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||||
@ -109,34 +107,31 @@ github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFi
|
|||||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56 h1:zviK8GX4VlMstrK3JkexM5UHjH1VOkRebH9y3jhSBGk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240412170617-26222e5d3d56/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk=
|
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||||
google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY=
|
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||||
google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
|
||||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
|
||||||
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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
53
go.work.sum
53
go.work.sum
@ -6,7 +6,10 @@ cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
|||||||
cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=
|
cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=
|
||||||
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
|
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
|
||||||
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||||
|
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||||
|
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
|
||||||
|
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
|
||||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
@ -51,6 +54,7 @@ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjK
|
|||||||
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
||||||
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
|
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
|
||||||
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||||
|
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
|
||||||
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
|
||||||
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/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||||
@ -100,7 +104,10 @@ github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nC
|
|||||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
|
||||||
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
||||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
|
||||||
@ -113,9 +120,13 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
||||||
github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM=
|
github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM=
|
||||||
github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
|
github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
||||||
@ -171,7 +182,10 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekf
|
|||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||||
|
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||||
|
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||||
|
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA=
|
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA=
|
||||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||||
@ -200,7 +214,10 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
@ -223,6 +240,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
|
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||||
github.com/influxdata/influxdb v1.7.6 h1:8mQ7A/V+3noMGCt/P9pD09ISaiz9XvgCk303UYA3gcs=
|
github.com/influxdata/influxdb v1.7.6 h1:8mQ7A/V+3noMGCt/P9pD09ISaiz9XvgCk303UYA3gcs=
|
||||||
github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
|
github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
|
||||||
github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
|
github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
|
||||||
@ -313,6 +332,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
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=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44=
|
github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
@ -424,6 +444,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1
|
|||||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@ -477,12 +499,15 @@ golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0
|
|||||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/exp v0.0.0-20230306221820-f0f767cdffd6/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230306221820-f0f767cdffd6/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/exp v0.0.0-20230807204917-050eac23e9de/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
golang.org/x/exp v0.0.0-20230807204917-050eac23e9de/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
||||||
|
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -514,6 +539,9 @@ golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
|||||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||||
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -524,7 +552,10 @@ golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
|
|||||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||||
|
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||||
|
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||||
|
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852 h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI=
|
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852 h1:xYq6+9AtI+xP3M4r0N1hCkHrInHDBohhquRgx9Kk6gI=
|
||||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -553,7 +584,13 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g=
|
||||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||||
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=
|
||||||
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||||
@ -568,7 +605,12 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
|||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
|
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
|
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||||
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
|
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||||
|
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||||
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
@ -591,6 +633,7 @@ golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM
|
|||||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
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-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
@ -604,6 +647,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
@ -615,11 +659,16 @@ google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWof
|
|||||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
|
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
|
||||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
|
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
|
||||||
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
|
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
|
||||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU=
|
google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo=
|
||||||
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M=
|
google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||||
|
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
|
||||||
|
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
|
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
|
@ -71,7 +71,6 @@ func TestBlockedHostEngine_IsBlocked(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ func TestBlockedHostEngine_IsBlocked_concurrent(t *testing.T) {
|
|||||||
engine := newBlockedHostEngine(rules)
|
engine := newBlockedHostEngine(rules)
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
for i := 0; i < routinesLimit; i++ {
|
for i := range routinesLimit {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
host := fmt.Sprintf("%d.%s", i, "block.test")
|
host := fmt.Sprintf("%d.%s", i, "block.test")
|
||||||
|
@ -236,7 +236,7 @@ func BenchmarkDefaultProfile_IsBlocked(b *testing.B) {
|
|||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
_ = a.IsBlocked(passReq, passAddrPort, nil)
|
_ = a.IsBlocked(passReq, passAddrPort, nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -247,7 +247,7 @@ func BenchmarkDefaultProfile_IsBlocked(b *testing.B) {
|
|||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
_ = a.IsBlocked(blockReq, passAddrPort, nil)
|
_ = a.IsBlocked(blockReq, passAddrPort, nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
)
|
)
|
||||||
@ -16,6 +17,9 @@ import (
|
|||||||
// NOTE: Do not change fields of this structure without incrementing
|
// NOTE: Do not change fields of this structure without incrementing
|
||||||
// [internal/profiledb/internal.FileCacheVersion].
|
// [internal/profiledb/internal.FileCacheVersion].
|
||||||
type Device struct {
|
type Device struct {
|
||||||
|
// Auth defines authentication settings of this device. It's never nil.
|
||||||
|
Auth *AuthSettings
|
||||||
|
|
||||||
// ID is the unique ID of the device.
|
// ID is the unique ID of the device.
|
||||||
ID DeviceID
|
ID DeviceID
|
||||||
|
|
||||||
@ -104,3 +108,20 @@ func NewDeviceName(s string) (n DeviceName, err error) {
|
|||||||
|
|
||||||
return DeviceName(s), nil
|
return DeviceName(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthSettings are the authentication settings of a device.
|
||||||
|
//
|
||||||
|
// NOTE: Do not change fields of this structure without incrementing
|
||||||
|
// [internal/profiledb/internal.FileCacheVersion].
|
||||||
|
type AuthSettings struct {
|
||||||
|
// PasswordHash is the hash of the auth password. It is never nil.
|
||||||
|
PasswordHash agdpasswd.Authenticator
|
||||||
|
|
||||||
|
// Enabled tells whether the authentication should be enabled at all.
|
||||||
|
// This must be true in order for all parameters to work.
|
||||||
|
Enabled bool
|
||||||
|
|
||||||
|
// DoHAuthOnly defines if the device should only be authenticated through
|
||||||
|
// DoH protocol.
|
||||||
|
DoHAuthOnly bool
|
||||||
|
}
|
||||||
|
@ -42,7 +42,6 @@ func TestNewDeviceName(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -17,33 +17,41 @@ const (
|
|||||||
// FilterListIDNone means that no filter were applied at all.
|
// FilterListIDNone means that no filter were applied at all.
|
||||||
FilterListIDNone FilterListID = ""
|
FilterListIDNone FilterListID = ""
|
||||||
|
|
||||||
// FilterListIDBlockedService is the shared filter list ID used when a
|
// FilterListIDBlockedService is the shared filter-list ID used when a
|
||||||
// request was blocked by the service blocker.
|
// request was blocked by the service blocker.
|
||||||
FilterListIDBlockedService FilterListID = "blocked_service"
|
FilterListIDBlockedService FilterListID = "blocked_service"
|
||||||
|
|
||||||
// FilterListIDCustom is the special shared filter list ID used when
|
// FilterListIDCustom is the special shared filter-list ID used when
|
||||||
// a request was filtered by a custom profile rule.
|
// a request was filtered by a custom profile rule.
|
||||||
FilterListIDCustom FilterListID = "custom"
|
FilterListIDCustom FilterListID = "custom"
|
||||||
|
|
||||||
// FilterListIDAdultBlocking is the special shared filter list ID used when
|
// FilterListIDAdultBlocking is the special shared filter-list ID used when
|
||||||
// a request was filtered by the adult content blocking filter.
|
// a request was filtered by the adult content blocking filter.
|
||||||
FilterListIDAdultBlocking FilterListID = "adult_blocking"
|
FilterListIDAdultBlocking FilterListID = "adult_blocking"
|
||||||
|
|
||||||
// FilterListIDSafeBrowsing is the special shared filter list ID used when
|
// FilterListIDSafeBrowsing is the special shared filter-list ID used when
|
||||||
// a request was filtered by the safe browsing filter.
|
// a request was filtered by the safe browsing filter.
|
||||||
FilterListIDSafeBrowsing FilterListID = "safe_browsing"
|
FilterListIDSafeBrowsing FilterListID = "safe_browsing"
|
||||||
|
|
||||||
// FilterListIDNewRegDomains is the special shared filter list ID used when
|
// FilterListIDNewRegDomains is the special shared filter-list ID used when
|
||||||
// a request was filtered by the newly registered domains filter.
|
// a request was filtered by the newly registered domains filter.
|
||||||
FilterListIDNewRegDomains FilterListID = "newly_registered_domains"
|
FilterListIDNewRegDomains FilterListID = "newly_registered_domains"
|
||||||
|
|
||||||
// FilterListIDGeneralSafeSearch is the shared filter list ID used when
|
// FilterListIDGeneralSafeSearch is the shared filter-list ID used when
|
||||||
// a request was modified by the general safe search filter.
|
// a request was modified by the general safe search filter.
|
||||||
FilterListIDGeneralSafeSearch FilterListID = "general_safe_search"
|
FilterListIDGeneralSafeSearch FilterListID = "general_safe_search"
|
||||||
|
|
||||||
// FilterListIDYoutubeSafeSearch is the special shared filter list ID used
|
// FilterListIDYoutubeSafeSearch is the special shared filter-list ID used
|
||||||
// when a request was modified by the YouTube safe search filter.
|
// when a request was modified by the YouTube safe search filter.
|
||||||
FilterListIDYoutubeSafeSearch FilterListID = "youtube_safe_search"
|
FilterListIDYoutubeSafeSearch FilterListID = "youtube_safe_search"
|
||||||
|
|
||||||
|
// FilterListIDAdGuardDNS is the special filter-list ID of the main AdGuard
|
||||||
|
// DNS filtering-rule list. For this list, rule statistics are collected.
|
||||||
|
FilterListIDAdGuardDNS FilterListID = "adguard_dns_filter"
|
||||||
|
|
||||||
|
// FilterListIDAdGuardPopup is the special filter-list ID of the AdGuard DNS
|
||||||
|
// list of popup domains.
|
||||||
|
FilterListIDAdGuardPopup FilterListID = "adguard_popup_filter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The maximum and minimum lengths of a filter list ID.
|
// The maximum and minimum lengths of a filter list ID.
|
||||||
@ -72,6 +80,21 @@ func NewFilterListID(s string) (id FilterListID, err error) {
|
|||||||
return FilterListID(s), nil
|
return FilterListID(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportsDNSRewrite returns true if the $dnsrewrite rules in filtering-rule
|
||||||
|
// lists with this ID should be processed.
|
||||||
|
func (id FilterListID) SupportsDNSRewrite() (ok bool) {
|
||||||
|
switch id {
|
||||||
|
case
|
||||||
|
FilterListIDAdGuardPopup,
|
||||||
|
FilterListIDCustom,
|
||||||
|
FilterListIDGeneralSafeSearch,
|
||||||
|
FilterListIDYoutubeSafeSearch:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FilterRuleText is the text of a single rule within a filter.
|
// FilterRuleText is the text of a single rule within a filter.
|
||||||
type FilterRuleText string
|
type FilterRuleText string
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ func TestNewFilterListID(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -86,7 +85,6 @@ func TestNewFilterRuleText(t *testing.T) {
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ func BenchmarkNewRequestID(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
reqIDSink = agd.NewRequestID()
|
reqIDSink = agd.NewRequestID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,23 +2,14 @@ package agd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"net/netip"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServerGroup is a group of DNS servers all of which use the same filtering
|
// ServerGroup is a group of DNS servers all of which use the same filtering
|
||||||
// settings.
|
// settings.
|
||||||
type ServerGroup struct {
|
type ServerGroup struct {
|
||||||
// BlockPageRedirect is the configuration for the server group's block page.
|
|
||||||
// BlockPageRedirect is never nil.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Use.
|
|
||||||
BlockPageRedirect *BlockPageRedirect
|
|
||||||
|
|
||||||
// DDR is the configuration for the server group's Discovery Of Designated
|
// DDR is the configuration for the server group's Discovery Of Designated
|
||||||
// Resolvers (DDR) handlers. DDR is never nil.
|
// Resolvers (DDR) handlers. DDR is never nil.
|
||||||
DDR *DDR
|
DDR *DDR
|
||||||
@ -60,11 +51,11 @@ type TLS struct {
|
|||||||
type DDR struct {
|
type DDR struct {
|
||||||
// DeviceTargets is the set of all domain names, subdomains of which should
|
// DeviceTargets is the set of all domain names, subdomains of which should
|
||||||
// be checked for DDR queries with device IDs.
|
// be checked for DDR queries with device IDs.
|
||||||
DeviceTargets *stringutil.Set
|
DeviceTargets *container.MapSet[string]
|
||||||
|
|
||||||
// PublicTargets is the set of all public domain names, DDR queries for
|
// PublicTargets is the set of all public domain names, DDR queries for
|
||||||
// which should be processed.
|
// which should be processed.
|
||||||
PublicTargets *stringutil.Set
|
PublicTargets *container.MapSet[string]
|
||||||
|
|
||||||
// DeviceRecordTemplates are used to respond to DDR queries from recognized
|
// DeviceRecordTemplates are used to respond to DDR queries from recognized
|
||||||
// devices.
|
// devices.
|
||||||
@ -78,81 +69,3 @@ type DDR struct {
|
|||||||
// name queries receive an NXDOMAIN response.
|
// name queries receive an NXDOMAIN response.
|
||||||
Enabled bool
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockPageRedirect is the configuration for a [ServerGroup]'s block page.
|
|
||||||
type BlockPageRedirect struct {
|
|
||||||
// Apply defines request parameters based on which the block page is shown
|
|
||||||
// always. If a request matches Apply, both [BlockPageRedirect.Skip] and
|
|
||||||
// [BlockPageRedirect.Probability] are ignored.
|
|
||||||
//
|
|
||||||
// If [BlockPageRedirect.Enabled] is true, Apply must not be nil.
|
|
||||||
Apply *BlockPageRedirectApply
|
|
||||||
|
|
||||||
// Skip defines request parameters based on which the block page is not
|
|
||||||
// shown, regardless of [BlockPageRedirect.Probability].
|
|
||||||
//
|
|
||||||
// If [BlockPageRedirect.Enabled] is true, Skip must not be nil.
|
|
||||||
Skip *BlockPageRedirectSkip
|
|
||||||
|
|
||||||
// IPv4 are the IPv4 addresses of the block page, used to respond to A
|
|
||||||
// queries.
|
|
||||||
//
|
|
||||||
// If [BlockPageRedirect.Enabled] is true, IPv4, [BlockPageRedirect.IPv6],
|
|
||||||
// or both must be filled.
|
|
||||||
IPv4 []netip.Addr
|
|
||||||
|
|
||||||
// IPv6 are the IPv6 addresses of the block page, used to respond to AAAA
|
|
||||||
// queries.
|
|
||||||
//
|
|
||||||
// If [BlockPageRedirect.Enabled] is true, [BlockPageRedirect.IPv4], IPv6,
|
|
||||||
// or both must be filled.
|
|
||||||
IPv6 []netip.Addr
|
|
||||||
|
|
||||||
// Probability defines the probability of responding with the block page IPs
|
|
||||||
// based on remote address. Probability must be between 0.0 and 1.0.
|
|
||||||
Probability Probability
|
|
||||||
|
|
||||||
// Enabled defines whether the block-page feature is enabled.
|
|
||||||
Enabled bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Probability is a type for probabilities ranging from 0.0 to 1.0.
|
|
||||||
type Probability float64
|
|
||||||
|
|
||||||
// NewProbability returns a properly converted Probability or an error.
|
|
||||||
func NewProbability(f float64) (prob Probability, err error) {
|
|
||||||
if math.IsNaN(f) || f < 0.0 || f > 1.0 {
|
|
||||||
return 0, fmt.Errorf("probability must be between 0.0 and 1.0; got %v", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Probability(f), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustNewProbability returns a properly converted Probability or panics with an
|
|
||||||
// error.
|
|
||||||
func MustNewProbability(f float64) (prob Probability) {
|
|
||||||
prob, err := NewProbability(f)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return prob
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockPageRedirectApply defines the conditions for applying the block-page
|
|
||||||
// logic for a particular request.
|
|
||||||
type BlockPageRedirectApply struct {
|
|
||||||
// ClientSubnets are the subnets for which block page is always enabled.
|
|
||||||
ClientSubnets []netip.Prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockPageRedirectSkip defines the conditions for skipping the block page
|
|
||||||
// logic for a particular request.
|
|
||||||
type BlockPageRedirectSkip struct {
|
|
||||||
// ClientSubnets are the subnets for which block page is always disabled.
|
|
||||||
ClientSubnets []netip.Prefix
|
|
||||||
|
|
||||||
// QuestionDomains are the domain names for which block page is always
|
|
||||||
// disabled.
|
|
||||||
QuestionDomains []string
|
|
||||||
}
|
|
||||||
|
59
internal/agdcache/agdcache.go
Normal file
59
internal/agdcache/agdcache.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Package agdcache contains cache interfaces, helpers, and implementations.
|
||||||
|
package agdcache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface is the cache interface.
|
||||||
|
type Interface[K, T any] interface {
|
||||||
|
// Set sets key and val as cache pair.
|
||||||
|
Set(key K, val T)
|
||||||
|
|
||||||
|
// SetWithExpire sets key and val as cache pair with expiration time.
|
||||||
|
SetWithExpire(key K, val T, expiration time.Duration)
|
||||||
|
|
||||||
|
// Get gets val from the cache using key.
|
||||||
|
Get(key K) (val T, ok bool)
|
||||||
|
|
||||||
|
// Clearer completely clears cache.
|
||||||
|
Clearer
|
||||||
|
|
||||||
|
// Len returns the number of items in the cache.
|
||||||
|
Len() (n int)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clearer is a partial cache interface.
|
||||||
|
type Clearer interface {
|
||||||
|
// Clear completely clears cache.
|
||||||
|
Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty is an [Interface] implementation that does nothing.
|
||||||
|
type Empty[K, T any] struct{}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Interface[any, any] = Empty[any, any]{}
|
||||||
|
|
||||||
|
// Set implements the [Interface] interface for Empty.
|
||||||
|
func (c Empty[K, T]) Set(key K, val T) {}
|
||||||
|
|
||||||
|
// SetWithExpire implements the [Interface] interface for Empty.
|
||||||
|
func (c Empty[K, T]) SetWithExpire(key K, val T, expiration time.Duration) {}
|
||||||
|
|
||||||
|
// Get implements the [Interface] interface for Empty.
|
||||||
|
func (c Empty[K, T]) Get(key K) (val T, ok bool) {
|
||||||
|
return val, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Clearer = Empty[any, any]{}
|
||||||
|
|
||||||
|
// Clear implements the [Interface] interface for Empty.
|
||||||
|
func (c Empty[K, T]) Clear() {}
|
||||||
|
|
||||||
|
// Len implements the [Interface] interface for Empty. n may include items that
|
||||||
|
// have expired, but have not yet been cleaned up.
|
||||||
|
func (c Empty[K, T]) Len() (n int) {
|
||||||
|
return 0
|
||||||
|
}
|
106
internal/agdcache/lru.go
Normal file
106
internal/agdcache/lru.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package agdcache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/bluele/gcache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LRUConfig is a configuration structure of a cache.
|
||||||
|
type LRUConfig struct {
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LRU is an [Interface] implementation.
|
||||||
|
type LRU[K, T any] struct {
|
||||||
|
cache gcache.Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLRU returns a new initialized LRU cache.
|
||||||
|
func NewLRU[K, T any](conf *LRUConfig) (c *LRU[K, T]) {
|
||||||
|
return &LRU[K, T]{
|
||||||
|
cache: gcache.New(conf.Size).LRU().Build(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Interface[any, any] = (*LRU[any, any])(nil)
|
||||||
|
|
||||||
|
// Set implements the [Interface] interface for *LRU.
|
||||||
|
func (c *LRU[K, T]) Set(key K, val T) {
|
||||||
|
err := c.cache.Set(key, val)
|
||||||
|
if err != nil {
|
||||||
|
// Shouldn't happen, since we don't set a serialization function.
|
||||||
|
panic(fmt.Errorf("agdcache: setting cache item: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWithExpire implements the [Interface] interface for *LRU.
|
||||||
|
func (c *LRU[K, T]) SetWithExpire(key K, val T, expiration time.Duration) {
|
||||||
|
err := c.cache.SetWithExpire(key, val, expiration)
|
||||||
|
if err != nil {
|
||||||
|
// Shouldn't happen, since we don't set a serialization function.
|
||||||
|
panic(fmt.Errorf("agdcache: setting cache item with expiration: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get implements the [Interface] interface for *LRU.
|
||||||
|
func (c *LRU[K, T]) Get(key K) (val T, ok bool) {
|
||||||
|
v, err := c.cache.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, gcache.KeyNotFoundError) {
|
||||||
|
// Shouldn't happen, since we don't set a serialization function.
|
||||||
|
panic(fmt.Errorf("agdcache: getting cache item: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// T may be an interface type, so check v against nil explicitly to prevent
|
||||||
|
// v.(T) below from panicking.
|
||||||
|
if v == nil {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.(T), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Clearer = (*LRU[any, any])(nil)
|
||||||
|
|
||||||
|
// Clear implements the [Interface] interface for *LRU.
|
||||||
|
func (c *LRU[K, T]) Clear() {
|
||||||
|
c.cache.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len implements the [Interface] interface for *LRU. n may include items
|
||||||
|
// that have expired, but have not yet been cleaned up.
|
||||||
|
func (c *LRU[K, T]) Len() (n int) {
|
||||||
|
const checkExpired = false
|
||||||
|
|
||||||
|
return c.cache.Len(checkExpired)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manager manages caches.
|
||||||
|
type Manager struct {
|
||||||
|
caches map[string]Clearer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewManager returns a new initialized *Manager.
|
||||||
|
func NewManager() (m *Manager) {
|
||||||
|
return &Manager{
|
||||||
|
caches: map[string]Clearer{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds cache by id.
|
||||||
|
func (m *Manager) Add(id string, cache Clearer) {
|
||||||
|
m.caches[id] = cache
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearByID clears cache by id.
|
||||||
|
func (m *Manager) ClearByID(id string) {
|
||||||
|
m.caches[id].Clear()
|
||||||
|
}
|
69
internal/agdcache/lru_test.go
Normal file
69
internal/agdcache/lru_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package agdcache_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdcache"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLRU(t *testing.T) {
|
||||||
|
const (
|
||||||
|
key = "key"
|
||||||
|
val = 123
|
||||||
|
|
||||||
|
nonExistingKey = "nonExistingKey"
|
||||||
|
)
|
||||||
|
|
||||||
|
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
cache.Set(key, val)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, cache.Len())
|
||||||
|
|
||||||
|
v, ok := cache.Get(key)
|
||||||
|
assert.Equal(t, val, v)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
v, ok = cache.Get(nonExistingKey)
|
||||||
|
assert.Equal(t, 0, v)
|
||||||
|
assert.False(t, ok)
|
||||||
|
|
||||||
|
cache.Clear()
|
||||||
|
|
||||||
|
assert.Equal(t, 0, cache.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager(t *testing.T) {
|
||||||
|
const (
|
||||||
|
key = "key"
|
||||||
|
val = 123
|
||||||
|
id = "cacheID"
|
||||||
|
|
||||||
|
nonExistingKey = "nonExistingKey"
|
||||||
|
)
|
||||||
|
|
||||||
|
cache := agdcache.NewLRU[string, int](&agdcache.LRUConfig{
|
||||||
|
Size: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
cache.Set(key, val)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, cache.Len())
|
||||||
|
|
||||||
|
v, ok := cache.Get(key)
|
||||||
|
assert.Equal(t, val, v)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
v, ok = cache.Get(nonExistingKey)
|
||||||
|
assert.Equal(t, 0, v)
|
||||||
|
assert.False(t, ok)
|
||||||
|
|
||||||
|
m := agdcache.NewManager()
|
||||||
|
m.Add(id, cache)
|
||||||
|
m.ClearByID(id)
|
||||||
|
|
||||||
|
assert.Equal(t, 0, cache.Len())
|
||||||
|
}
|
@ -15,6 +15,7 @@ import (
|
|||||||
// HTTP header value constants.
|
// HTTP header value constants.
|
||||||
const (
|
const (
|
||||||
HdrValApplicationJSON = "application/json"
|
HdrValApplicationJSON = "application/json"
|
||||||
|
HdrValGzip = "gzip"
|
||||||
HdrValTextCSV = "text/csv"
|
HdrValTextCSV = "text/csv"
|
||||||
HdrValTextHTML = "text/html"
|
HdrValTextHTML = "text/html"
|
||||||
HdrValTextPlain = "text/plain"
|
HdrValTextPlain = "text/plain"
|
||||||
|
@ -34,22 +34,18 @@ func NewClient(conf *ClientConfig) (c *Client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get is a wrapper around http.Client.Get.
|
// Get is a wrapper around [http.Client.Get].
|
||||||
//
|
//
|
||||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||||
// close resp.Body when done reading from it.
|
// close resp.Body when done reading from it.
|
||||||
//
|
|
||||||
// See also go doc http.Client.Get.
|
|
||||||
func (c *Client) Get(ctx context.Context, u *url.URL) (resp *http.Response, err error) {
|
func (c *Client) Get(ctx context.Context, u *url.URL) (resp *http.Response, err error) {
|
||||||
return c.do(ctx, http.MethodGet, u, "", nil)
|
return c.do(ctx, http.MethodGet, u, "", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post is a wrapper around http.Client.Post.
|
// Post is a wrapper around [http.Client.Post].
|
||||||
//
|
//
|
||||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||||
// close resp.Body when done reading from it.
|
// close resp.Body when done reading from it.
|
||||||
//
|
|
||||||
// See also go doc http.Client.Post.
|
|
||||||
func (c *Client) Post(
|
func (c *Client) Post(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
u *url.URL,
|
u *url.URL,
|
||||||
@ -59,7 +55,7 @@ func (c *Client) Post(
|
|||||||
return c.do(ctx, http.MethodPost, u, contentType, body)
|
return c.do(ctx, http.MethodPost, u, contentType, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put is a wrapper around http.Client.Do.
|
// Put is a wrapper around [http.Client.Put].
|
||||||
//
|
//
|
||||||
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
// When err is nil, resp always contains a non-nil resp.Body. Caller should
|
||||||
// close resp.Body when done reading from it.
|
// close resp.Body when done reading from it.
|
||||||
@ -72,7 +68,7 @@ func (c *Client) Put(
|
|||||||
return c.do(ctx, http.MethodPut, u, contentType, body)
|
return c.do(ctx, http.MethodPut, u, contentType, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// do is a wrapper around http.Client.Do.
|
// do is a wrapper around [http.Client.Do].
|
||||||
func (c *Client) do(
|
func (c *Client) do(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
method string,
|
method string,
|
||||||
@ -98,7 +94,8 @@ func (c *Client) do(
|
|||||||
|
|
||||||
resp, err = c.http.Do(req)
|
resp, err = c.http.Do(req)
|
||||||
if err != nil && resp != nil && resp.Header != nil {
|
if err != nil && resp != nil && resp.Header != nil {
|
||||||
// A non-nil Response with a non-nil error only occurs when CheckRedirect fails.
|
// A non-nil Response with a non-nil error only occurs when
|
||||||
|
// CheckRedirect fails.
|
||||||
return resp, WrapServerError(err, resp)
|
return resp, WrapServerError(err, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
package agdnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"net"
|
|
||||||
"net/netip"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Resolver is the DNS resolver interface.
|
|
||||||
//
|
|
||||||
// See [net.Resolver].
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Move to golibs and unite with the one in module dnsproxy.
|
|
||||||
type Resolver interface {
|
|
||||||
// LookupNetIP returns a slice of host's IP addresses of family specified by
|
|
||||||
// fam, which must be either [netutil.AddrFamilyIPv4] or
|
|
||||||
// [netutil.AddrFamilyIPv6].
|
|
||||||
LookupNetIP(
|
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultResolver uses [net.DefaultResolver] to resolve addresses.
|
|
||||||
type DefaultResolver struct{}
|
|
||||||
|
|
||||||
// type check
|
|
||||||
var _ Resolver = DefaultResolver{}
|
|
||||||
|
|
||||||
// LookupNetIP implements the [Resolver] interface for DefaultResolver.
|
|
||||||
func (DefaultResolver) LookupNetIP(
|
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error) {
|
|
||||||
switch fam {
|
|
||||||
case netutil.AddrFamilyIPv4:
|
|
||||||
return net.DefaultResolver.LookupNetIP(ctx, "ip4", host)
|
|
||||||
case netutil.AddrFamilyIPv6:
|
|
||||||
return net.DefaultResolver.LookupNetIP(ctx, "ip6", host)
|
|
||||||
default:
|
|
||||||
return nil, net.UnknownNetworkError(fam.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolveCache is a simple address resolving cache.
|
|
||||||
type resolveCache map[string]*resolveCacheItem
|
|
||||||
|
|
||||||
// resolveCacheItem is an item of [resolveCache].
|
|
||||||
type resolveCacheItem struct {
|
|
||||||
refrTime time.Time
|
|
||||||
ips []netip.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
// CachingResolver caches resolved results for hosts for a certain time,
|
|
||||||
// regardless of the actual TTLs of the records. It is used for caching the
|
|
||||||
// results of lookups of hostnames that don't change their IP addresses often.
|
|
||||||
type CachingResolver struct {
|
|
||||||
resolver Resolver
|
|
||||||
|
|
||||||
// mu protects ip4 and ip6.
|
|
||||||
mu *sync.Mutex
|
|
||||||
ipv4 resolveCache
|
|
||||||
ipv6 resolveCache
|
|
||||||
|
|
||||||
ttl time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCachingResolver returns a new caching resolver.
|
|
||||||
func NewCachingResolver(resolver Resolver, ttl time.Duration) (c *CachingResolver) {
|
|
||||||
return &CachingResolver{
|
|
||||||
resolver: resolver,
|
|
||||||
|
|
||||||
mu: &sync.Mutex{},
|
|
||||||
ipv4: resolveCache{},
|
|
||||||
ipv6: resolveCache{},
|
|
||||||
|
|
||||||
ttl: ttl,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// type check
|
|
||||||
var _ Resolver = (*CachingResolver)(nil)
|
|
||||||
|
|
||||||
// LookupNetIP implements the [Resolver] interface for *CachingResolver. host
|
|
||||||
// should be normalized. Slice ips and its elements must not be mutated.
|
|
||||||
func (c *CachingResolver) LookupNetIP(
|
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error) {
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
|
|
||||||
var item *resolveCacheItem
|
|
||||||
switch fam {
|
|
||||||
case netutil.AddrFamilyIPv4:
|
|
||||||
item = c.ipv4[host]
|
|
||||||
case netutil.AddrFamilyIPv6:
|
|
||||||
item = c.ipv6[host]
|
|
||||||
default:
|
|
||||||
return nil, net.UnknownNetworkError(fam.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if item == nil || time.Since(item.refrTime) > c.ttl {
|
|
||||||
item, err = c.resolve(ctx, fam, host)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ips, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve looks up the IP addresses for host and puts them into the cache.
|
|
||||||
func (c *CachingResolver) resolve(
|
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (item *resolveCacheItem, err error) {
|
|
||||||
var ips []netip.Addr
|
|
||||||
|
|
||||||
refrTime := time.Now()
|
|
||||||
|
|
||||||
// Don't resolve IP addresses.
|
|
||||||
ip := ipFromHost(host, fam)
|
|
||||||
if ip != (netip.Addr{}) {
|
|
||||||
ips = []netip.Addr{ip}
|
|
||||||
|
|
||||||
// Set the refresh time to the maximum date that time.Duration allows to
|
|
||||||
// prevent this item from refreshing.
|
|
||||||
refrTime = time.Unix(0, math.MaxInt64)
|
|
||||||
} else {
|
|
||||||
ips, err = c.resolver.LookupNetIP(ctx, fam, host)
|
|
||||||
if err != nil {
|
|
||||||
if !isExpectedLookupError(fam, err) {
|
|
||||||
return nil, fmt.Errorf("resolving %s addr for %q: %w", fam, host, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("caching resolver: warning: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var cache resolveCache
|
|
||||||
if fam == netutil.AddrFamilyIPv4 {
|
|
||||||
cache = c.ipv4
|
|
||||||
} else {
|
|
||||||
cache = c.ipv6
|
|
||||||
}
|
|
||||||
|
|
||||||
item = &resolveCacheItem{
|
|
||||||
refrTime: refrTime,
|
|
||||||
ips: ips,
|
|
||||||
}
|
|
||||||
|
|
||||||
cache[host] = item
|
|
||||||
|
|
||||||
return item, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipFromHost parses host as if it'd be an IP address of specified fam. It
|
|
||||||
// returns an empty netip.
|
|
||||||
func ipFromHost(host string, fam netutil.AddrFamily) (ip netip.Addr) {
|
|
||||||
var famFunc func(netip.Addr) (ok bool)
|
|
||||||
switch fam {
|
|
||||||
case netutil.AddrFamilyIPv4:
|
|
||||||
famFunc = netip.Addr.Is4
|
|
||||||
case netutil.AddrFamilyIPv6:
|
|
||||||
famFunc = netip.Addr.Is6
|
|
||||||
default:
|
|
||||||
return netip.Addr{}
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, err := netip.ParseAddr(host)
|
|
||||||
if err != nil || !famFunc(ip) {
|
|
||||||
return netip.Addr{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ip
|
|
||||||
}
|
|
||||||
|
|
||||||
// isExpectedLookupError returns true if the error is an expected lookup error.
|
|
||||||
func isExpectedLookupError(fam netutil.AddrFamily, err error) (ok bool) {
|
|
||||||
var dnsErr *net.DNSError
|
|
||||||
if fam == netutil.AddrFamilyIPv6 && errors.As(err, &dnsErr) {
|
|
||||||
// It's expected that Go default DNS resolver returns a DNS error in
|
|
||||||
// some cases when it receives an empty response. It's unclear what
|
|
||||||
// exactly triggers this error, though.
|
|
||||||
//
|
|
||||||
// TODO(ameshkov): Consider researching this in detail.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var addrErr *net.AddrError
|
|
||||||
if !errors.As(err, &addrErr) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect the error about no suitable addresses. For example, no IPv6
|
|
||||||
// addresses for a host that does have IPv4 ones.
|
|
||||||
//
|
|
||||||
// See function filterAddrList in ${GOROOT}/src/net/ipsock.go.
|
|
||||||
return addrErr.Err == "no suitable address found"
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package agdnet_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/netip"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCachingResolver_Resolve(t *testing.T) {
|
|
||||||
const testHost = "addr.example"
|
|
||||||
|
|
||||||
var numLookups uint64
|
|
||||||
wantIPv4 := []netip.Addr{netip.MustParseAddr("1.2.3.4")}
|
|
||||||
wantIPv6 := []netip.Addr{netip.MustParseAddr("1234::5678")}
|
|
||||||
r := &agdtest.Resolver{
|
|
||||||
OnLookupNetIP: func(
|
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error) {
|
|
||||||
numLookups++
|
|
||||||
|
|
||||||
if fam == netutil.AddrFamilyIPv4 {
|
|
||||||
return wantIPv4, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cached := agdnet.NewCachingResolver(r, 1*timeutil.Day)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
host string
|
|
||||||
wantIPs []netip.Addr
|
|
||||||
wantNum uint64
|
|
||||||
fam netutil.AddrFamily
|
|
||||||
}{{
|
|
||||||
name: "initial",
|
|
||||||
host: testHost,
|
|
||||||
wantIPs: wantIPv4,
|
|
||||||
wantNum: 1,
|
|
||||||
fam: netutil.AddrFamilyIPv4,
|
|
||||||
}, {
|
|
||||||
name: "cached",
|
|
||||||
host: testHost,
|
|
||||||
wantIPs: wantIPv4,
|
|
||||||
wantNum: 1,
|
|
||||||
fam: netutil.AddrFamilyIPv4,
|
|
||||||
}, {
|
|
||||||
name: "other_network",
|
|
||||||
host: testHost,
|
|
||||||
wantIPs: nil,
|
|
||||||
wantNum: 2,
|
|
||||||
fam: netutil.AddrFamilyIPv6,
|
|
||||||
}, {
|
|
||||||
name: "ipv4",
|
|
||||||
host: wantIPv4[0].String(),
|
|
||||||
wantIPs: wantIPv4,
|
|
||||||
wantNum: 2,
|
|
||||||
fam: netutil.AddrFamilyIPv4,
|
|
||||||
}, {
|
|
||||||
name: "ipv6",
|
|
||||||
host: wantIPv6[0].String(),
|
|
||||||
wantIPs: wantIPv6,
|
|
||||||
wantNum: 2,
|
|
||||||
fam: netutil.AddrFamilyIPv6,
|
|
||||||
}}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
got, err := cached.LookupNetIP(ctx, tc.fam, tc.host)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, tc.wantNum, numLookups)
|
|
||||||
assert.Equal(t, tc.wantIPs, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
51
internal/agdpasswd/authenticator.go
Normal file
51
internal/agdpasswd/authenticator.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Package agdpasswd contains authentication utils.
|
||||||
|
package agdpasswd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Authenticator represents a password authenticator.
|
||||||
|
type Authenticator interface {
|
||||||
|
// Authenticate returns true if the given passwd is allowed.
|
||||||
|
Authenticate(ctx context.Context, passwd []byte) (ok bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowAuthenticator is an empty authenticator implementation that always
|
||||||
|
// grants access, regardless of any restrictions.
|
||||||
|
type AllowAuthenticator struct{}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Authenticator = AllowAuthenticator{}
|
||||||
|
|
||||||
|
// Authenticate implements the [Authenticator] interface for AllowAuthenticator.
|
||||||
|
func (AllowAuthenticator) Authenticate(_ context.Context, _ []byte) (ok bool) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PasswordHashBcrypt is the Bcrypt implementation of [Authenticator].
|
||||||
|
type PasswordHashBcrypt struct {
|
||||||
|
// bytes contains the password hash.
|
||||||
|
bytes []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPasswordHashBcrypt returns a new bcrypt hashed password authenticator.
|
||||||
|
func NewPasswordHashBcrypt(hashedPassword []byte) (p *PasswordHashBcrypt) {
|
||||||
|
return &PasswordHashBcrypt{bytes: hashedPassword}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PasswordHash returns password hash bytes slice.
|
||||||
|
func (p *PasswordHashBcrypt) PasswordHash() (b []byte) {
|
||||||
|
return p.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Authenticator = (*PasswordHashBcrypt)(nil)
|
||||||
|
|
||||||
|
// Authenticate implements the [Authenticator] interface for
|
||||||
|
// *PasswordHashBcrypt.
|
||||||
|
func (p *PasswordHashBcrypt) Authenticate(_ context.Context, passwd []byte) (ok bool) {
|
||||||
|
return bcrypt.CompareHashAndPassword(p.bytes, passwd) == nil
|
||||||
|
}
|
49
internal/agdpasswd/authenticator_test.go
Normal file
49
internal/agdpasswd/authenticator_test.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package agdpasswd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
testutil.DiscardLogOutput(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPasswordHashBcrypt_Authenticate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const passwd = "mypassword"
|
||||||
|
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(passwd), 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
authenticator := agdpasswd.NewPasswordHashBcrypt(hash)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
want assert.BoolAssertionFunc
|
||||||
|
name string
|
||||||
|
pass string
|
||||||
|
}{{
|
||||||
|
want: assert.True,
|
||||||
|
name: "success",
|
||||||
|
pass: passwd,
|
||||||
|
}, {
|
||||||
|
want: assert.False,
|
||||||
|
name: "fail",
|
||||||
|
pass: "an-other-passwd",
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tc.want(t, authenticator.Authenticate(context.Background(), []byte(tc.pass)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,10 @@ import (
|
|||||||
|
|
||||||
// Refresher is the interface for entities that can update themselves.
|
// Refresher is the interface for entities that can update themselves.
|
||||||
type Refresher interface {
|
type Refresher interface {
|
||||||
|
// Refresh is called by a [RefreshWorker]. The error returned by Refresh is
|
||||||
|
// only returned from [RefreshWorker.Shutdown] and only when
|
||||||
|
// [RefreshWorkerConfig.RefreshOnShutdown] is true. In all other cases, the
|
||||||
|
// error is ignored, and refreshers must handle error reporting themselves.
|
||||||
Refresh(ctx context.Context) (err error)
|
Refresh(ctx context.Context) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,11 +25,9 @@ type Refresher interface {
|
|||||||
type RefreshWorker struct {
|
type RefreshWorker struct {
|
||||||
done chan unit
|
done chan unit
|
||||||
context func() (ctx context.Context, cancel context.CancelFunc)
|
context func() (ctx context.Context, cancel context.CancelFunc)
|
||||||
logRoutine func(format string, args ...any)
|
|
||||||
tick *time.Ticker
|
tick *time.Ticker
|
||||||
rand *rand.Rand
|
rand *rand.Rand
|
||||||
refr Refresher
|
refr Refresher
|
||||||
errColl errcoll.Interface
|
|
||||||
name string
|
name string
|
||||||
maxStartSleep time.Duration
|
maxStartSleep time.Duration
|
||||||
|
|
||||||
@ -40,12 +42,6 @@ type RefreshWorkerConfig struct {
|
|||||||
// Refresher is the entity being refreshed.
|
// Refresher is the entity being refreshed.
|
||||||
Refresher Refresher
|
Refresher Refresher
|
||||||
|
|
||||||
// ErrColl is used to collect errors during refreshes.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Remove this and make all Refreshers handle their own
|
|
||||||
// errors.
|
|
||||||
ErrColl errcoll.Interface
|
|
||||||
|
|
||||||
// Name is the name of this worker. It is used for logging and error
|
// Name is the name of this worker. It is used for logging and error
|
||||||
// collecting.
|
// collecting.
|
||||||
//
|
//
|
||||||
@ -64,12 +60,6 @@ type RefreshWorkerConfig struct {
|
|||||||
// that should persist to disk or remote storage before shutting down.
|
// that should persist to disk or remote storage before shutting down.
|
||||||
RefreshOnShutdown bool
|
RefreshOnShutdown bool
|
||||||
|
|
||||||
// RoutineLogsAreDebug, if true, instructs the worker to write initial and
|
|
||||||
// final log messages for each singular refresh on the Debug level rather
|
|
||||||
// than on the Info one. This is useful to prevent routine logs from
|
|
||||||
// workers with a small interval from overflowing with messages.
|
|
||||||
RoutineLogsAreDebug bool
|
|
||||||
|
|
||||||
// RandomizeStart, if true, instructs the worker to sleep before starting a
|
// RandomizeStart, if true, instructs the worker to sleep before starting a
|
||||||
// refresh. The duration of the sleep is a random duration of up to 10 % of
|
// refresh. The duration of the sleep is a random duration of up to 10 % of
|
||||||
// Interval.
|
// Interval.
|
||||||
@ -82,14 +72,6 @@ type RefreshWorkerConfig struct {
|
|||||||
// NewRefreshWorker returns a new valid *RefreshWorker with the provided
|
// NewRefreshWorker returns a new valid *RefreshWorker with the provided
|
||||||
// parameters. c must not be nil.
|
// parameters. c must not be nil.
|
||||||
func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
||||||
// TODO(a.garipov): Add log.WithLevel.
|
|
||||||
var logRoutine func(format string, args ...any)
|
|
||||||
if c.RoutineLogsAreDebug {
|
|
||||||
logRoutine = log.Debug
|
|
||||||
} else {
|
|
||||||
logRoutine = log.Info
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxStartSleep time.Duration
|
var maxStartSleep time.Duration
|
||||||
var rng *rand.Rand
|
var rng *rand.Rand
|
||||||
if c.RandomizeStart {
|
if c.RandomizeStart {
|
||||||
@ -100,11 +82,9 @@ func NewRefreshWorker(c *RefreshWorkerConfig) (w *RefreshWorker) {
|
|||||||
return &RefreshWorker{
|
return &RefreshWorker{
|
||||||
done: make(chan unit),
|
done: make(chan unit),
|
||||||
context: c.Context,
|
context: c.Context,
|
||||||
logRoutine: logRoutine,
|
|
||||||
tick: time.NewTicker(c.Interval),
|
tick: time.NewTicker(c.Interval),
|
||||||
rand: rng,
|
rand: rng,
|
||||||
refr: c.Refresher,
|
refr: c.Refresher,
|
||||||
errColl: c.ErrColl,
|
|
||||||
name: c.Name,
|
name: c.Name,
|
||||||
maxStartSleep: maxStartSleep,
|
maxStartSleep: maxStartSleep,
|
||||||
refrOnShutdown: c.RefreshOnShutdown,
|
refrOnShutdown: c.RefreshOnShutdown,
|
||||||
@ -172,7 +152,7 @@ func (w *RefreshWorker) sleepRandom() (shouldRefresh bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sleepDur := time.Duration(w.rand.Int63n(int64(w.maxStartSleep)))
|
sleepDur := time.Duration(w.rand.Int63n(int64(w.maxStartSleep)))
|
||||||
w.logRoutine("worker %q: sleeping for %s before refresh", w.name, sleepDur)
|
log.Debug("worker %q: sleeping for %s before refresh", w.name, sleepDur)
|
||||||
|
|
||||||
timer := time.NewTimer(sleepDur)
|
timer := time.NewTimer(sleepDur)
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -197,24 +177,51 @@ func (w *RefreshWorker) sleepRandom() (shouldRefresh bool) {
|
|||||||
|
|
||||||
// refresh refreshes the entity and logs the status of the refresh.
|
// refresh refreshes the entity and logs the status of the refresh.
|
||||||
func (w *RefreshWorker) refresh() {
|
func (w *RefreshWorker) refresh() {
|
||||||
name := w.name
|
|
||||||
w.logRoutine("worker %q: refreshing", name)
|
|
||||||
|
|
||||||
// TODO(a.garipov): Consider adding a helper for enriching errors with
|
// TODO(a.garipov): Consider adding a helper for enriching errors with
|
||||||
// context deadline data without duplication. See an example in method
|
// context deadline data without duplication. See an example in method
|
||||||
// filter.refreshableFilter.refresh.
|
// filter.refreshableFilter.refresh.
|
||||||
ctx, cancel := w.context()
|
ctx, cancel := w.context()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
log.Debug("worker %q: starting refresh", name)
|
_ = w.refr.Refresh(ctx)
|
||||||
err := w.refr.Refresh(ctx)
|
}
|
||||||
log.Debug("worker %q: finished refresh", name)
|
|
||||||
|
|
||||||
|
// RefresherWithErrColl reports all refresh errors to errColl and logs them
|
||||||
|
// using a provided logging function.
|
||||||
|
type RefresherWithErrColl struct {
|
||||||
|
refr Refresher
|
||||||
|
log func(format string, args ...any)
|
||||||
|
errColl errcoll.Interface
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRefresherWithErrColl wraps refr into a refresher that collects errors and
|
||||||
|
// logs them.
|
||||||
|
func NewRefresherWithErrColl(
|
||||||
|
refr Refresher,
|
||||||
|
logFunc func(format string, args ...any),
|
||||||
|
errColl errcoll.Interface,
|
||||||
|
prefix string,
|
||||||
|
) (wrapped *RefresherWithErrColl) {
|
||||||
|
return &RefresherWithErrColl{
|
||||||
|
refr: refr,
|
||||||
|
log: logFunc,
|
||||||
|
errColl: errColl,
|
||||||
|
prefix: prefix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// type check
|
||||||
|
var _ Refresher = (*RefresherWithErrColl)(nil)
|
||||||
|
|
||||||
|
// Refresh implements the [Refresher] interface for *RefresherWithErrColl.
|
||||||
|
func (r *RefresherWithErrColl) Refresh(ctx context.Context) (err error) {
|
||||||
|
err = r.refr.Refresh(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errcoll.Collectf(ctx, w.errColl, "%s: %w", name, err)
|
err = fmt.Errorf("%s: %w", r.prefix, err)
|
||||||
|
r.log("%s", err)
|
||||||
return
|
r.errColl.Collect(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.logRoutine("worker %q: refreshed successfully", name)
|
return err
|
||||||
}
|
}
|
||||||
|
@ -42,52 +42,39 @@ func newTestRefresher(t *testing.T, respErr error) (refr *agdtest.Refresher, syn
|
|||||||
return refr, syncCh
|
return refr, syncCh
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRefrConf returns worker configuration.
|
// newRefrConfig returns worker configuration.
|
||||||
func newRefrConf(
|
func newRefrConfig(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
refr agdservice.Refresher,
|
refr agdservice.Refresher,
|
||||||
ivl time.Duration,
|
ivl time.Duration,
|
||||||
refrOnShutDown bool,
|
refrOnShutDown bool,
|
||||||
errCh chan sig,
|
|
||||||
) (conf *agdservice.RefreshWorkerConfig) {
|
) (conf *agdservice.RefreshWorkerConfig) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
pt := testutil.PanicT{}
|
|
||||||
|
|
||||||
errColl := &agdtest.ErrorCollector{
|
|
||||||
OnCollect: func(_ context.Context, _ error) {
|
|
||||||
testutil.RequireSend(pt, errCh, sig{}, testTimeout)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return &agdservice.RefreshWorkerConfig{
|
return &agdservice.RefreshWorkerConfig{
|
||||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||||
return context.WithTimeout(context.Background(), testTimeout)
|
return context.WithTimeout(context.Background(), testTimeout)
|
||||||
},
|
},
|
||||||
Refresher: refr,
|
Refresher: refr,
|
||||||
ErrColl: errColl,
|
Name: name,
|
||||||
Name: name,
|
Interval: ivl,
|
||||||
Interval: ivl,
|
RefreshOnShutdown: refrOnShutDown,
|
||||||
RefreshOnShutdown: refrOnShutDown,
|
RandomizeStart: false,
|
||||||
RoutineLogsAreDebug: false,
|
|
||||||
RandomizeStart: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRefreshWorker(t *testing.T) {
|
func TestRefreshWorker(t *testing.T) {
|
||||||
t.Run("success", func(t *testing.T) {
|
t.Run("success", func(t *testing.T) {
|
||||||
refr, syncCh := newTestRefresher(t, nil)
|
refr, syncCh := newTestRefresher(t, nil)
|
||||||
errCh := make(chan sig, 1)
|
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConf(t, refr, testIvl, false, errCh))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, refr, testIvl, false))
|
||||||
|
|
||||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||||
require.Empty(t, errCh)
|
|
||||||
|
|
||||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -95,12 +82,12 @@ func TestRefreshWorker(t *testing.T) {
|
|||||||
refr, syncCh := newTestRefresher(t, nil)
|
refr, syncCh := newTestRefresher(t, nil)
|
||||||
errCh := make(chan sig, 1)
|
errCh := make(chan sig, 1)
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConf(t, refr, testIvlLong, true, errCh))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, refr, testIvlLong, true))
|
||||||
|
|
||||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||||
@ -109,33 +96,29 @@ func TestRefreshWorker(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("error", func(t *testing.T) {
|
t.Run("error", func(t *testing.T) {
|
||||||
errRefr, syncCh := newTestRefresher(t, testError)
|
errRefr, syncCh := newTestRefresher(t, testError)
|
||||||
errCh := make(chan sig, 1)
|
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConf(t, errRefr, testIvl, false, errCh))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvl, false))
|
||||||
|
|
||||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||||
testutil.RequireReceive(t, errCh, testTimeout)
|
|
||||||
|
|
||||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("error_on_shutdown", func(t *testing.T) {
|
t.Run("error_on_shutdown", func(t *testing.T) {
|
||||||
errRefr, syncCh := newTestRefresher(t, testError)
|
errRefr, syncCh := newTestRefresher(t, testError)
|
||||||
errCh := make(chan sig, 1)
|
|
||||||
|
|
||||||
w := agdservice.NewRefreshWorker(newRefrConf(t, errRefr, testIvlLong, true, errCh))
|
w := agdservice.NewRefreshWorker(newRefrConfig(t, errRefr, testIvlLong, true))
|
||||||
|
|
||||||
err := w.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err := w.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = w.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
err = w.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
assert.ErrorIs(t, err, testError)
|
assert.ErrorIs(t, err, testError)
|
||||||
|
|
||||||
testutil.RequireReceive(t, syncCh, testTimeout)
|
testutil.RequireReceive(t, syncCh, testTimeout)
|
||||||
require.Empty(t, errCh)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
package agdtest
|
package agdtest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
@ -27,16 +25,3 @@ func NewConstructor() (c *dnsmsg.Constructor) {
|
|||||||
func NewCloner() (c *dnsmsg.Cloner) {
|
func NewCloner() (c *dnsmsg.Cloner) {
|
||||||
return dnsmsg.NewCloner(dnsmsg.EmptyClonerStat{})
|
return dnsmsg.NewCloner(dnsmsg.EmptyClonerStat{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextWithTimeout is a helper that creates a new context with timeout and
|
|
||||||
// registers ctx's cleanup with t.Cleanup.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Move to golibs.
|
|
||||||
func ContextWithTimeout(tb testing.TB, timeout time.Duration) (ctx context.Context) {
|
|
||||||
tb.Helper()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
||||||
tb.Cleanup(cancel)
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
"github.com/AdguardTeam/AdGuardDNS/internal/billstat"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||||
@ -52,27 +52,20 @@ func (a *AccessManager) IsBlockedIP(ip netip.Addr) (blocked bool) {
|
|||||||
return a.OnIsBlockedIP(ip)
|
return a.OnIsBlockedIP(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package agdnet
|
// Package agdpasswd
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ agdnet.Resolver = (*Resolver)(nil)
|
var _ agdpasswd.Authenticator = (*Authenticator)(nil)
|
||||||
|
|
||||||
// Resolver is an [agdnet.Resolver] for tests.
|
// Authenticator is an [agdpasswd.Authenticator] for tests.
|
||||||
type Resolver struct {
|
type Authenticator struct {
|
||||||
OnLookupNetIP func(
|
OnAuthenticate func(ctx context.Context, passwd []byte) (ok bool)
|
||||||
ctx context.Context,
|
|
||||||
fam netutil.AddrFamily,
|
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupNetIP implements the [agdnet.Resolver] interface for *Resolver.
|
// Authenticate implements the [agdpasswd.Authenticator] interface for
|
||||||
func (r *Resolver) LookupNetIP(
|
// *Authenticator.
|
||||||
ctx context.Context,
|
func (a *Authenticator) Authenticate(ctx context.Context, passwd []byte) (ok bool) {
|
||||||
fam netutil.AddrFamily,
|
return a.OnAuthenticate(ctx, passwd)
|
||||||
host string,
|
|
||||||
) (ips []netip.Addr, err error) {
|
|
||||||
return r.OnLookupNetIP(ctx, fam, host)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package agdservice
|
// Package agdservice
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.31.0
|
// protoc-gen-go v1.33.0
|
||||||
// protoc v4.25.1
|
// protoc v4.25.3
|
||||||
// source: backend.proto
|
// source: backend.proto
|
||||||
|
|
||||||
package backendpb
|
package backendpb
|
||||||
@ -359,11 +359,12 @@ type DeviceSettings struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
FilteringEnabled bool `protobuf:"varint,3,opt,name=filtering_enabled,json=filteringEnabled,proto3" json:"filtering_enabled,omitempty"`
|
FilteringEnabled bool `protobuf:"varint,3,opt,name=filtering_enabled,json=filteringEnabled,proto3" json:"filtering_enabled,omitempty"`
|
||||||
LinkedIp []byte `protobuf:"bytes,4,opt,name=linked_ip,json=linkedIp,proto3" json:"linked_ip,omitempty"`
|
LinkedIp []byte `protobuf:"bytes,4,opt,name=linked_ip,json=linkedIp,proto3" json:"linked_ip,omitempty"`
|
||||||
DedicatedIps [][]byte `protobuf:"bytes,5,rep,name=dedicated_ips,json=dedicatedIps,proto3" json:"dedicated_ips,omitempty"`
|
DedicatedIps [][]byte `protobuf:"bytes,5,rep,name=dedicated_ips,json=dedicatedIps,proto3" json:"dedicated_ips,omitempty"`
|
||||||
|
Authentication *AuthenticationSettings `protobuf:"bytes,6,opt,name=authentication,proto3" json:"authentication,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeviceSettings) Reset() {
|
func (x *DeviceSettings) Reset() {
|
||||||
@ -433,6 +434,13 @@ func (x *DeviceSettings) GetDedicatedIps() [][]byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *DeviceSettings) GetAuthentication() *AuthenticationSettings {
|
||||||
|
if x != nil {
|
||||||
|
return x.Authentication
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ParentalSettings struct {
|
type ParentalSettings struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -1179,6 +1187,81 @@ func (x *CidrRange) GetPrefix() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthenticationSettings struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
DohAuthOnly bool `protobuf:"varint,1,opt,name=doh_auth_only,json=dohAuthOnly,proto3" json:"doh_auth_only,omitempty"`
|
||||||
|
// Types that are assignable to DohPasswordHash:
|
||||||
|
//
|
||||||
|
// *AuthenticationSettings_PasswordHashBcrypt
|
||||||
|
DohPasswordHash isAuthenticationSettings_DohPasswordHash `protobuf_oneof:"doh_password_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *AuthenticationSettings) Reset() {
|
||||||
|
*x = AuthenticationSettings{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_backend_proto_msgTypes[16]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *AuthenticationSettings) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*AuthenticationSettings) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *AuthenticationSettings) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_backend_proto_msgTypes[16]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use AuthenticationSettings.ProtoReflect.Descriptor instead.
|
||||||
|
func (*AuthenticationSettings) Descriptor() ([]byte, []int) {
|
||||||
|
return file_backend_proto_rawDescGZIP(), []int{16}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *AuthenticationSettings) GetDohAuthOnly() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.DohAuthOnly
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AuthenticationSettings) GetDohPasswordHash() isAuthenticationSettings_DohPasswordHash {
|
||||||
|
if m != nil {
|
||||||
|
return m.DohPasswordHash
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *AuthenticationSettings) GetPasswordHashBcrypt() []byte {
|
||||||
|
if x, ok := x.GetDohPasswordHash().(*AuthenticationSettings_PasswordHashBcrypt); ok {
|
||||||
|
return x.PasswordHashBcrypt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type isAuthenticationSettings_DohPasswordHash interface {
|
||||||
|
isAuthenticationSettings_DohPasswordHash()
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthenticationSettings_PasswordHashBcrypt struct {
|
||||||
|
PasswordHashBcrypt []byte `protobuf:"bytes,2,opt,name=password_hash_bcrypt,json=passwordHashBcrypt,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*AuthenticationSettings_PasswordHashBcrypt) isAuthenticationSettings_DohPasswordHash() {}
|
||||||
|
|
||||||
var File_backend_proto protoreflect.FileDescriptor
|
var File_backend_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_backend_proto_rawDesc = []byte{
|
var file_backend_proto_rawDesc = []byte{
|
||||||
@ -1263,7 +1346,7 @@ var file_backend_proto_rawDesc = []byte{
|
|||||||
0x63, 0x6b, 0x44, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x63, 0x6b, 0x44, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x72, 0x64, 0x18,
|
0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x72, 0x64, 0x18,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x64, 0x22,
|
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x64, 0x22,
|
||||||
0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
0xe4, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x67, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
0x67, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||||
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
|
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
|
||||||
@ -1273,110 +1356,123 @@ var file_backend_proto_rawDesc = []byte{
|
|||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x49, 0x70,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x49, 0x70,
|
||||||
0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x70,
|
0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x70,
|
||||||
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74,
|
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x64, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74,
|
||||||
0x65, 0x64, 0x49, 0x70, 0x73, 0x22, 0x87, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
0x65, 0x64, 0x49, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||||
0x61, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e,
|
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||||
0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61,
|
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65,
|
||||||
0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61, 0x64,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||||
0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x87, 0x02, 0x0a, 0x10, 0x50, 0x61, 0x72, 0x65, 0x6e,
|
||||||
0x41, 0x64, 0x75, 0x6c, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
|
0x74, 0x61, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65,
|
||||||
0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01,
|
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e,
|
||||||
0x28, 0x08, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x53, 0x61, 0x66, 0x65, 0x53,
|
0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x61,
|
||||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65,
|
0x64, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63,
|
||||||
0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01,
|
0x6b, 0x41, 0x64, 0x75, 0x6c, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
||||||
0x28, 0x08, 0x52, 0x11, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x53, 0x61, 0x66, 0x65, 0x53,
|
0x6c, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20,
|
||||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64,
|
0x01, 0x28, 0x08, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x53, 0x61, 0x66, 0x65,
|
||||||
0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62,
|
||||||
0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
0x65, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x04, 0x20,
|
||||||
0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01,
|
0x01, 0x28, 0x08, 0x52, 0x11, 0x79, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x53, 0x61, 0x66, 0x65,
|
||||||
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74,
|
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x22,
|
0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
|
||||||
0x54, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69,
|
0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||||
0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x6d, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x73, 0x12, 0x2d, 0x0a, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x06, 0x20,
|
||||||
0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12, 0x2e, 0x0a, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52,
|
0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65,
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x57, 0x65, 0x65,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
|
||||||
0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
0x22, 0x54, 0x0a, 0x10, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x74,
|
||||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x0b, 0x57, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
0x69, 0x6e, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x6d, 0x7a, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
|
0x09, 0x52, 0x03, 0x74, 0x6d, 0x7a, 0x12, 0x2e, 0x0a, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79,
|
||||||
0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x6d,
|
0x52, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x57, 0x65,
|
||||||
0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x65, 0x6b, 0x6c,
|
||||||
0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x75, 0x65, 0x12,
|
0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xd8, 0x01, 0x0a, 0x0b, 0x57, 0x65, 0x65, 0x6b, 0x6c,
|
||||||
0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44,
|
0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20,
|
||||||
0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x03,
|
|
||||||
0x74, 0x68, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52,
|
|
||||||
0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x68, 0x75, 0x12, 0x1b, 0x0a, 0x03, 0x66, 0x72, 0x69,
|
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67,
|
|
||||||
0x65, 0x52, 0x03, 0x66, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20,
|
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03,
|
0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03,
|
||||||
0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
0x6d, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x03, 0x74, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x75, 0x6e,
|
0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x75, 0x65,
|
||||||
0x22, 0x68, 0x0a, 0x08, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x05,
|
0x12, 0x1b, 0x0a, 0x03, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e,
|
||||||
0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
|
0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a,
|
||||||
|
0x03, 0x74, 0x68, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79,
|
||||||
|
0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x74, 0x68, 0x75, 0x12, 0x1b, 0x0a, 0x03, 0x66, 0x72,
|
||||||
|
0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e,
|
||||||
|
0x67, 0x65, 0x52, 0x03, 0x66, 0x72, 0x69, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x61, 0x74, 0x18, 0x06,
|
||||||
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
|
||||||
|
0x03, 0x73, 0x61, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x73, 0x75, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x09, 0x2e, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x03, 0x73, 0x75,
|
||||||
|
0x6e, 0x22, 0x68, 0x0a, 0x08, 0x44, 0x61, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2f, 0x0a,
|
||||||
|
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67,
|
||||||
|
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44,
|
||||||
|
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b,
|
||||||
|
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
|
||||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
|
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
|
||||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a,
|
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x3f, 0x0a, 0x11, 0x52,
|
||||||
0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f,
|
0x75, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72,
|
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x3f, 0x0a, 0x11, 0x52, 0x75,
|
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64,
|
||||||
0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x3e, 0x0a, 0x14,
|
||||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x75, 0x73, 0x74,
|
||||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73,
|
0x6f, 0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x3e, 0x0a, 0x14, 0x42,
|
0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36,
|
||||||
0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x22, 0x16, 0x0a, 0x14,
|
||||||
0x6d, 0x49, 0x50, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x58, 0x44, 0x4f,
|
||||||
0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18,
|
0x4d, 0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x69, 0x70, 0x76, 0x36, 0x22, 0x16, 0x0a, 0x14, 0x42,
|
0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x49, 0x50, 0x22, 0x15, 0x0a, 0x13, 0x42, 0x6c,
|
||||||
0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x58, 0x44, 0x4f, 0x4d,
|
0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45,
|
||||||
0x41, 0x49, 0x4e, 0x22, 0x14, 0x0a, 0x12, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d,
|
0x44, 0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c,
|
||||||
0x6f, 0x64, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x49, 0x50, 0x22, 0x15, 0x0a, 0x13, 0x42, 0x6c, 0x6f,
|
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f,
|
||||||
0x63, 0x6b, 0x69, 0x6e, 0x67, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45, 0x44,
|
0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||||
0x22, 0xe3, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69,
|
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61,
|
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
|
||||||
0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
0x10, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d,
|
||||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02,
|
||||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25,
|
||||||
0x6c, 0x61, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65,
|
0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79,
|
||||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a,
|
0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x04,
|
||||||
0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x61,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x75,
|
0x73, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x18, 0x0a,
|
||||||
0x6e, 0x74, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x04, 0x20,
|
0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73,
|
0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x65,
|
||||||
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x18, 0x0a, 0x07,
|
0x73, 0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x61, 0x6c,
|
||||||
0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x71,
|
0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x03,
|
||||||
0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x65, 0x73,
|
0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d,
|
||||||
0x73, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x61, 0x6c, 0x6c,
|
0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x31, 0x0a,
|
||||||
0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28,
|
0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18,
|
||||||
0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x61,
|
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67,
|
||||||
0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12, 0x31, 0x0a, 0x0e,
|
0x65, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72,
|
||||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02,
|
0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x43, 0x69, 0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65,
|
0x6e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69,
|
||||||
0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x43, 0x69, 0x64, 0x72, 0x12,
|
0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69,
|
||||||
0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e,
|
0x73, 0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x6c,
|
||||||
0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x6c, 0x69, 0x73,
|
0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6c,
|
||||||
0x74, 0x41, 0x73, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73,
|
0x6f, 0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x72,
|
||||||
0x74, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x6c, 0x6f,
|
0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63,
|
||||||
0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x41, 0x73, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x62, 0x6c, 0x6f,
|
0x6b, 0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73,
|
||||||
0x63, 0x6b, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x75,
|
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x69,
|
||||||
0x6c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12,
|
0x64, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
|
0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||||
0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x69, 0x64,
|
0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x41, 0x75,
|
||||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
0x69, 0x6e, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x6f, 0x68, 0x5f, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x32, 0x8a, 0x01, 0x0a, 0x0a, 0x44, 0x4e, 0x53,
|
0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x64, 0x6f, 0x68,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x44, 0x4e,
|
0x41, 0x75, 0x74, 0x68, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x32, 0x0a, 0x14, 0x70, 0x61, 0x73, 0x73,
|
||||||
0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x13, 0x2e, 0x44, 0x4e, 0x53, 0x50,
|
0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x62, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||||
0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a,
|
0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x42, 0x63, 0x72, 0x79, 0x70, 0x74, 0x42, 0x13, 0x0a, 0x11,
|
||||||
0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x6c, 0x6c,
|
0x64, 0x6f, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
|
||||||
0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
|
0x68, 0x32, 0x8a, 0x01, 0x0a, 0x0a, 0x44, 0x4e, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||||
0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
|
0x12, 0x34, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
|
||||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
0x65, 0x73, 0x12, 0x13, 0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
|
||||||
0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x3d, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x67,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f,
|
||||||
0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x73,
|
0x66, 0x69, 0x6c, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x16, 0x73, 0x61, 0x76, 0x65, 0x44, 0x65,
|
||||||
0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x10, 0x44, 0x4e, 0x53, 0x50,
|
0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74,
|
||||||
0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02,
|
0x12, 0x12, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67,
|
||||||
0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x53, 0x74, 0x61, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x42, 0x3d,
|
||||||
|
0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x64, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2e, 0x62, 0x61,
|
||||||
|
0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
||||||
|
0x74, 0x65, 0x64, 0x42, 0x10, 0x44, 0x4e, 0x53, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73,
|
||||||
|
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0xa2, 0x02, 0x03, 0x44, 0x4e, 0x53, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1391,63 +1487,65 @@ func file_backend_proto_rawDescGZIP() []byte {
|
|||||||
return file_backend_proto_rawDescData
|
return file_backend_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
|
var file_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||||
var file_backend_proto_goTypes = []interface{}{
|
var file_backend_proto_goTypes = []interface{}{
|
||||||
(*DNSProfilesRequest)(nil), // 0: DNSProfilesRequest
|
(*DNSProfilesRequest)(nil), // 0: DNSProfilesRequest
|
||||||
(*DNSProfile)(nil), // 1: DNSProfile
|
(*DNSProfile)(nil), // 1: DNSProfile
|
||||||
(*SafeBrowsingSettings)(nil), // 2: SafeBrowsingSettings
|
(*SafeBrowsingSettings)(nil), // 2: SafeBrowsingSettings
|
||||||
(*DeviceSettings)(nil), // 3: DeviceSettings
|
(*DeviceSettings)(nil), // 3: DeviceSettings
|
||||||
(*ParentalSettings)(nil), // 4: ParentalSettings
|
(*ParentalSettings)(nil), // 4: ParentalSettings
|
||||||
(*ScheduleSettings)(nil), // 5: ScheduleSettings
|
(*ScheduleSettings)(nil), // 5: ScheduleSettings
|
||||||
(*WeeklyRange)(nil), // 6: WeeklyRange
|
(*WeeklyRange)(nil), // 6: WeeklyRange
|
||||||
(*DayRange)(nil), // 7: DayRange
|
(*DayRange)(nil), // 7: DayRange
|
||||||
(*RuleListsSettings)(nil), // 8: RuleListsSettings
|
(*RuleListsSettings)(nil), // 8: RuleListsSettings
|
||||||
(*BlockingModeCustomIP)(nil), // 9: BlockingModeCustomIP
|
(*BlockingModeCustomIP)(nil), // 9: BlockingModeCustomIP
|
||||||
(*BlockingModeNXDOMAIN)(nil), // 10: BlockingModeNXDOMAIN
|
(*BlockingModeNXDOMAIN)(nil), // 10: BlockingModeNXDOMAIN
|
||||||
(*BlockingModeNullIP)(nil), // 11: BlockingModeNullIP
|
(*BlockingModeNullIP)(nil), // 11: BlockingModeNullIP
|
||||||
(*BlockingModeREFUSED)(nil), // 12: BlockingModeREFUSED
|
(*BlockingModeREFUSED)(nil), // 12: BlockingModeREFUSED
|
||||||
(*DeviceBillingStat)(nil), // 13: DeviceBillingStat
|
(*DeviceBillingStat)(nil), // 13: DeviceBillingStat
|
||||||
(*AccessSettings)(nil), // 14: AccessSettings
|
(*AccessSettings)(nil), // 14: AccessSettings
|
||||||
(*CidrRange)(nil), // 15: CidrRange
|
(*CidrRange)(nil), // 15: CidrRange
|
||||||
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
|
(*AuthenticationSettings)(nil), // 16: AuthenticationSettings
|
||||||
(*durationpb.Duration)(nil), // 17: google.protobuf.Duration
|
(*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp
|
||||||
(*emptypb.Empty)(nil), // 18: google.protobuf.Empty
|
(*durationpb.Duration)(nil), // 18: google.protobuf.Duration
|
||||||
|
(*emptypb.Empty)(nil), // 19: google.protobuf.Empty
|
||||||
}
|
}
|
||||||
var file_backend_proto_depIdxs = []int32{
|
var file_backend_proto_depIdxs = []int32{
|
||||||
16, // 0: DNSProfilesRequest.sync_time:type_name -> google.protobuf.Timestamp
|
17, // 0: DNSProfilesRequest.sync_time:type_name -> google.protobuf.Timestamp
|
||||||
2, // 1: DNSProfile.safe_browsing:type_name -> SafeBrowsingSettings
|
2, // 1: DNSProfile.safe_browsing:type_name -> SafeBrowsingSettings
|
||||||
4, // 2: DNSProfile.parental:type_name -> ParentalSettings
|
4, // 2: DNSProfile.parental:type_name -> ParentalSettings
|
||||||
8, // 3: DNSProfile.rule_lists:type_name -> RuleListsSettings
|
8, // 3: DNSProfile.rule_lists:type_name -> RuleListsSettings
|
||||||
3, // 4: DNSProfile.devices:type_name -> DeviceSettings
|
3, // 4: DNSProfile.devices:type_name -> DeviceSettings
|
||||||
17, // 5: DNSProfile.filtered_response_ttl:type_name -> google.protobuf.Duration
|
18, // 5: DNSProfile.filtered_response_ttl:type_name -> google.protobuf.Duration
|
||||||
9, // 6: DNSProfile.blocking_mode_custom_ip:type_name -> BlockingModeCustomIP
|
9, // 6: DNSProfile.blocking_mode_custom_ip:type_name -> BlockingModeCustomIP
|
||||||
10, // 7: DNSProfile.blocking_mode_nxdomain:type_name -> BlockingModeNXDOMAIN
|
10, // 7: DNSProfile.blocking_mode_nxdomain:type_name -> BlockingModeNXDOMAIN
|
||||||
11, // 8: DNSProfile.blocking_mode_null_ip:type_name -> BlockingModeNullIP
|
11, // 8: DNSProfile.blocking_mode_null_ip:type_name -> BlockingModeNullIP
|
||||||
12, // 9: DNSProfile.blocking_mode_refused:type_name -> BlockingModeREFUSED
|
12, // 9: DNSProfile.blocking_mode_refused:type_name -> BlockingModeREFUSED
|
||||||
14, // 10: DNSProfile.access:type_name -> AccessSettings
|
14, // 10: DNSProfile.access:type_name -> AccessSettings
|
||||||
5, // 11: ParentalSettings.schedule:type_name -> ScheduleSettings
|
16, // 11: DeviceSettings.authentication:type_name -> AuthenticationSettings
|
||||||
6, // 12: ScheduleSettings.weeklyRange:type_name -> WeeklyRange
|
5, // 12: ParentalSettings.schedule:type_name -> ScheduleSettings
|
||||||
7, // 13: WeeklyRange.mon:type_name -> DayRange
|
6, // 13: ScheduleSettings.weeklyRange:type_name -> WeeklyRange
|
||||||
7, // 14: WeeklyRange.tue:type_name -> DayRange
|
7, // 14: WeeklyRange.mon:type_name -> DayRange
|
||||||
7, // 15: WeeklyRange.wed:type_name -> DayRange
|
7, // 15: WeeklyRange.tue:type_name -> DayRange
|
||||||
7, // 16: WeeklyRange.thu:type_name -> DayRange
|
7, // 16: WeeklyRange.wed:type_name -> DayRange
|
||||||
7, // 17: WeeklyRange.fri:type_name -> DayRange
|
7, // 17: WeeklyRange.thu:type_name -> DayRange
|
||||||
7, // 18: WeeklyRange.sat:type_name -> DayRange
|
7, // 18: WeeklyRange.fri:type_name -> DayRange
|
||||||
7, // 19: WeeklyRange.sun:type_name -> DayRange
|
7, // 19: WeeklyRange.sat:type_name -> DayRange
|
||||||
17, // 20: DayRange.start:type_name -> google.protobuf.Duration
|
7, // 20: WeeklyRange.sun:type_name -> DayRange
|
||||||
17, // 21: DayRange.end:type_name -> google.protobuf.Duration
|
18, // 21: DayRange.start:type_name -> google.protobuf.Duration
|
||||||
16, // 22: DeviceBillingStat.last_activity_time:type_name -> google.protobuf.Timestamp
|
18, // 22: DayRange.end:type_name -> google.protobuf.Duration
|
||||||
15, // 23: AccessSettings.allowlist_cidr:type_name -> CidrRange
|
17, // 23: DeviceBillingStat.last_activity_time:type_name -> google.protobuf.Timestamp
|
||||||
15, // 24: AccessSettings.blocklist_cidr:type_name -> CidrRange
|
15, // 24: AccessSettings.allowlist_cidr:type_name -> CidrRange
|
||||||
0, // 25: DNSService.getDNSProfiles:input_type -> DNSProfilesRequest
|
15, // 25: AccessSettings.blocklist_cidr:type_name -> CidrRange
|
||||||
13, // 26: DNSService.saveDevicesBillingStat:input_type -> DeviceBillingStat
|
0, // 26: DNSService.getDNSProfiles:input_type -> DNSProfilesRequest
|
||||||
1, // 27: DNSService.getDNSProfiles:output_type -> DNSProfile
|
13, // 27: DNSService.saveDevicesBillingStat:input_type -> DeviceBillingStat
|
||||||
18, // 28: DNSService.saveDevicesBillingStat:output_type -> google.protobuf.Empty
|
1, // 28: DNSService.getDNSProfiles:output_type -> DNSProfile
|
||||||
27, // [27:29] is the sub-list for method output_type
|
19, // 29: DNSService.saveDevicesBillingStat:output_type -> google.protobuf.Empty
|
||||||
25, // [25:27] is the sub-list for method input_type
|
28, // [28:30] is the sub-list for method output_type
|
||||||
25, // [25:25] is the sub-list for extension type_name
|
26, // [26:28] is the sub-list for method input_type
|
||||||
25, // [25:25] is the sub-list for extension extendee
|
26, // [26:26] is the sub-list for extension type_name
|
||||||
0, // [0:25] is the sub-list for field type_name
|
26, // [26:26] is the sub-list for extension extendee
|
||||||
|
0, // [0:26] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_backend_proto_init() }
|
func init() { file_backend_proto_init() }
|
||||||
@ -1648,6 +1746,18 @@ func file_backend_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
file_backend_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*AuthenticationSettings); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
file_backend_proto_msgTypes[1].OneofWrappers = []interface{}{
|
file_backend_proto_msgTypes[1].OneofWrappers = []interface{}{
|
||||||
(*DNSProfile_BlockingModeCustomIp)(nil),
|
(*DNSProfile_BlockingModeCustomIp)(nil),
|
||||||
@ -1655,13 +1765,16 @@ func file_backend_proto_init() {
|
|||||||
(*DNSProfile_BlockingModeNullIp)(nil),
|
(*DNSProfile_BlockingModeNullIp)(nil),
|
||||||
(*DNSProfile_BlockingModeRefused)(nil),
|
(*DNSProfile_BlockingModeRefused)(nil),
|
||||||
}
|
}
|
||||||
|
file_backend_proto_msgTypes[16].OneofWrappers = []interface{}{
|
||||||
|
(*AuthenticationSettings_PasswordHashBcrypt)(nil),
|
||||||
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_backend_proto_rawDesc,
|
RawDescriptor: file_backend_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 16,
|
NumMessages: 17,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
@ -66,6 +66,7 @@ message DeviceSettings {
|
|||||||
bool filtering_enabled = 3;
|
bool filtering_enabled = 3;
|
||||||
bytes linked_ip = 4;
|
bytes linked_ip = 4;
|
||||||
repeated bytes dedicated_ips = 5;
|
repeated bytes dedicated_ips = 5;
|
||||||
|
AuthenticationSettings authentication = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ParentalSettings {
|
message ParentalSettings {
|
||||||
@ -136,3 +137,10 @@ message CidrRange {
|
|||||||
bytes address = 1;
|
bytes address = 1;
|
||||||
uint32 prefix = 2;
|
uint32 prefix = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AuthenticationSettings {
|
||||||
|
bool doh_auth_only = 1;
|
||||||
|
oneof doh_password_hash {
|
||||||
|
bytes password_hash_bcrypt = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.3.0
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
// - protoc v4.25.1
|
// - protoc v4.25.3
|
||||||
// source: backend.proto
|
// source: backend.proto
|
||||||
|
|
||||||
package backendpb
|
package backendpb
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdprotobuf"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdprotobuf"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
@ -355,6 +356,37 @@ func (x *ScheduleSettings) toInternal() (sch *agd.ParentalProtectionSchedule, er
|
|||||||
return sch, nil
|
return sch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toInternal converts a protobuf custom blocking-mode to an internal one.
|
||||||
|
// Assumes that at least one IP address is specified in the result blocking-mode
|
||||||
|
// object.
|
||||||
|
func (pbm *BlockingModeCustomIP) toInternal() (m dnsmsg.BlockingMode, err error) {
|
||||||
|
custom := &dnsmsg.BlockingModeCustomIP{}
|
||||||
|
|
||||||
|
// TODO(a.garipov): Only one IPv4 address is supported on protobuf side.
|
||||||
|
var ipv4Addr netip.Addr
|
||||||
|
err = ipv4Addr.UnmarshalBinary(pbm.Ipv4)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("bad custom ipv4: %w", err)
|
||||||
|
} else if ipv4Addr.IsValid() {
|
||||||
|
custom.IPv4 = []netip.Addr{ipv4Addr}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(a.garipov): Only one IPv6 address is supported on protobuf side.
|
||||||
|
var ipv6Addr netip.Addr
|
||||||
|
err = ipv6Addr.UnmarshalBinary(pbm.Ipv6)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("bad custom ipv6: %w", err)
|
||||||
|
} else if ipv6Addr.IsValid() {
|
||||||
|
custom.IPv6 = []netip.Addr{ipv6Addr}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(custom.IPv4)+len(custom.IPv6) == 0 {
|
||||||
|
return nil, errors.Error("no valid custom ips found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return custom, nil
|
||||||
|
}
|
||||||
|
|
||||||
// blockingModeToInternal converts a protobuf blocking-mode sum-type to an
|
// blockingModeToInternal converts a protobuf blocking-mode sum-type to an
|
||||||
// internal one. If pbm is nil, blockingModeToInternal returns a null-IP
|
// internal one. If pbm is nil, blockingModeToInternal returns a null-IP
|
||||||
// blocking mode.
|
// blocking mode.
|
||||||
@ -363,18 +395,7 @@ func blockingModeToInternal(pbm isDNSProfile_BlockingMode) (m dnsmsg.BlockingMod
|
|||||||
case nil:
|
case nil:
|
||||||
return &dnsmsg.BlockingModeNullIP{}, nil
|
return &dnsmsg.BlockingModeNullIP{}, nil
|
||||||
case *DNSProfile_BlockingModeCustomIp:
|
case *DNSProfile_BlockingModeCustomIp:
|
||||||
custom := &dnsmsg.BlockingModeCustomIP{}
|
return pbm.BlockingModeCustomIp.toInternal()
|
||||||
err = custom.IPv4.UnmarshalBinary(pbm.BlockingModeCustomIp.Ipv4)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("bad custom ipv4: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = custom.IPv6.UnmarshalBinary(pbm.BlockingModeCustomIp.Ipv6)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("bad custom ipv6: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return custom, nil
|
|
||||||
case *DNSProfile_BlockingModeNxdomain:
|
case *DNSProfile_BlockingModeNxdomain:
|
||||||
return &dnsmsg.BlockingModeNXDOMAIN{}, nil
|
return &dnsmsg.BlockingModeNXDOMAIN{}, nil
|
||||||
case *DNSProfile_BlockingModeNullIp:
|
case *DNSProfile_BlockingModeNullIp:
|
||||||
@ -443,6 +464,11 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auth, err := ds.Authentication.toInternal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("auth: %s: %w", ds.Id, err)
|
||||||
|
}
|
||||||
|
|
||||||
id, err := agd.NewDeviceID(ds.Id)
|
id, err := agd.NewDeviceID(ds.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("device id: %s: %w", ds.Id, err)
|
return nil, fmt.Errorf("device id: %s: %w", ds.Id, err)
|
||||||
@ -454,6 +480,7 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &agd.Device{
|
return &agd.Device{
|
||||||
|
Auth: auth,
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: name,
|
Name: name,
|
||||||
LinkedIP: linkedIP,
|
LinkedIP: linkedIP,
|
||||||
@ -462,6 +489,44 @@ func (ds *DeviceSettings) toInternal(bindSet netutil.SubnetSet) (dev *agd.Device
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toInternal converts a protobuf auth settings structure to an internal one.
|
||||||
|
// If x is nil, toInternal returns non-nil settings with enabled field set to
|
||||||
|
// false.
|
||||||
|
func (x *AuthenticationSettings) toInternal() (s *agd.AuthSettings, err error) {
|
||||||
|
if x == nil {
|
||||||
|
return &agd.AuthSettings{
|
||||||
|
Enabled: false,
|
||||||
|
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ph, err := dohPasswordToInternal(x.DohPasswordHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("password hash: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &agd.AuthSettings{
|
||||||
|
PasswordHash: ph,
|
||||||
|
Enabled: true,
|
||||||
|
DoHAuthOnly: x.DohAuthOnly,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dohPasswordToInternal converts a protobuf DoH password hash sum-type to an
|
||||||
|
// internal one.
|
||||||
|
func dohPasswordToInternal(
|
||||||
|
pbp isAuthenticationSettings_DohPasswordHash,
|
||||||
|
) (p agdpasswd.Authenticator, err error) {
|
||||||
|
switch pbp := pbp.(type) {
|
||||||
|
case nil:
|
||||||
|
return agdpasswd.AllowAuthenticator{}, nil
|
||||||
|
case *AuthenticationSettings_PasswordHashBcrypt:
|
||||||
|
return agdpasswd.NewPasswordHashBcrypt(pbp.PasswordHashBcrypt), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("bad pb auth doh password hash %T(%[1]v)", pbp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rulesToInternal is a helper that converts the filter rules from the backend
|
// rulesToInternal is a helper that converts the filter rules from the backend
|
||||||
// response to AdGuard DNS filtering rules.
|
// response to AdGuard DNS filtering rules.
|
||||||
func rulesToInternal(
|
func rulesToInternal(
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdpasswd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtime"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
@ -92,7 +93,7 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
|
|
||||||
assert.NotEqual(t, newProfile(t), got)
|
assert.NotEqual(t, newProfile(t), got)
|
||||||
assert.NotEqual(t, newDevices(t), gotDevices)
|
assert.NotEqual(t, newDevices(t), gotDevices)
|
||||||
assert.Len(t, gotDevices, 1)
|
assert.Len(t, gotDevices, 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty", func(t *testing.T) {
|
t.Run("empty", func(t *testing.T) {
|
||||||
@ -153,6 +154,16 @@ func TestDNSProfile_ToInternal(t *testing.T) {
|
|||||||
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
testutil.AssertErrorMsg(t, "blocking mode: bad custom ipv6: unexpected slice size", err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("nil_ips_blocking_mode", func(t *testing.T) {
|
||||||
|
dp := NewTestDNSProfile(t)
|
||||||
|
bm := dp.BlockingMode.(*DNSProfile_BlockingModeCustomIp)
|
||||||
|
bm.BlockingModeCustomIp.Ipv4 = nil
|
||||||
|
bm.BlockingModeCustomIp.Ipv6 = nil
|
||||||
|
|
||||||
|
_, _, err := dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||||
|
testutil.AssertErrorMsg(t, "blocking mode: no valid custom ips found", err)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("nil_blocking_mode", func(t *testing.T) {
|
t.Run("nil_blocking_mode", func(t *testing.T) {
|
||||||
dp := NewTestDNSProfile(t)
|
dp := NewTestDNSProfile(t)
|
||||||
dp.BlockingMode = nil
|
dp.BlockingMode = nil
|
||||||
@ -244,17 +255,33 @@ func NewTestDNSProfile(tb testing.TB) (dp *DNSProfile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
devices := []*DeviceSettings{{
|
devices := []*DeviceSettings{{
|
||||||
Id: "118ffe93",
|
Id: "1111aaaa",
|
||||||
Name: "118ffe93-name",
|
Name: "1111aaaa-name",
|
||||||
FilteringEnabled: false,
|
FilteringEnabled: false,
|
||||||
LinkedIp: ipToBytes(tb, netip.MustParseAddr("1.1.1.1")),
|
LinkedIp: ipToBytes(tb, netip.MustParseAddr("1.1.1.1")),
|
||||||
DedicatedIps: [][]byte{ipToBytes(tb, netip.MustParseAddr("1.1.1.2"))},
|
DedicatedIps: [][]byte{ipToBytes(tb, netip.MustParseAddr("1.1.1.2"))},
|
||||||
}, {
|
}, {
|
||||||
Id: "b9e1a762",
|
Id: "2222bbbb",
|
||||||
Name: "b9e1a762-name",
|
Name: "2222bbbb-name",
|
||||||
FilteringEnabled: true,
|
FilteringEnabled: true,
|
||||||
LinkedIp: ipToBytes(tb, netip.MustParseAddr("2.2.2.2")),
|
LinkedIp: ipToBytes(tb, netip.MustParseAddr("2.2.2.2")),
|
||||||
DedicatedIps: nil,
|
DedicatedIps: nil,
|
||||||
|
Authentication: &AuthenticationSettings{
|
||||||
|
DohAuthOnly: true,
|
||||||
|
DohPasswordHash: &AuthenticationSettings_PasswordHashBcrypt{
|
||||||
|
PasswordHashBcrypt: []byte("test-hash"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
Id: "3333cccc",
|
||||||
|
Name: "3333cccc-name",
|
||||||
|
FilteringEnabled: false,
|
||||||
|
LinkedIp: ipToBytes(tb, netip.MustParseAddr("3.3.3.3")),
|
||||||
|
DedicatedIps: nil,
|
||||||
|
Authentication: &AuthenticationSettings{
|
||||||
|
DohAuthOnly: false,
|
||||||
|
DohPasswordHash: nil,
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
return &DNSProfile{
|
return &DNSProfile{
|
||||||
@ -358,8 +385,8 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wantBlockingMode := &dnsmsg.BlockingModeCustomIP{
|
wantBlockingMode := &dnsmsg.BlockingModeCustomIP{
|
||||||
IPv4: netip.MustParseAddr("1.2.3.4"),
|
IPv4: []netip.Addr{netip.MustParseAddr("1.2.3.4")},
|
||||||
IPv6: netip.MustParseAddr("1234::cdef"),
|
IPv6: []netip.Addr{netip.MustParseAddr("1234::cdef")},
|
||||||
}
|
}
|
||||||
|
|
||||||
wantAccess := access.NewDefaultProfile(&access.ProfileConfig{
|
wantAccess := access.NewDefaultProfile(&access.ProfileConfig{
|
||||||
@ -376,8 +403,9 @@ func newProfile(tb testing.TB) (p *agd.Profile) {
|
|||||||
ID: testProfileID,
|
ID: testProfileID,
|
||||||
UpdateTime: TestUpdTime,
|
UpdateTime: TestUpdTime,
|
||||||
DeviceIDs: []agd.DeviceID{
|
DeviceIDs: []agd.DeviceID{
|
||||||
"118ffe93",
|
"1111aaaa",
|
||||||
"b9e1a762",
|
"2222bbbb",
|
||||||
|
"3333cccc",
|
||||||
},
|
},
|
||||||
RuleListIDs: []agd.FilterListID{"1"},
|
RuleListIDs: []agd.FilterListID{"1"},
|
||||||
CustomRules: []agd.FilterRuleText{"||example.org^"},
|
CustomRules: []agd.FilterRuleText{"||example.org^"},
|
||||||
@ -399,17 +427,38 @@ func newDevices(t *testing.T) (d []*agd.Device) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
return []*agd.Device{{
|
return []*agd.Device{{
|
||||||
ID: "118ffe93",
|
Auth: &agd.AuthSettings{
|
||||||
|
Enabled: false,
|
||||||
|
DoHAuthOnly: false,
|
||||||
|
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||||
|
},
|
||||||
|
ID: "1111aaaa",
|
||||||
LinkedIP: netip.MustParseAddr("1.1.1.1"),
|
LinkedIP: netip.MustParseAddr("1.1.1.1"),
|
||||||
Name: "118ffe93-name",
|
Name: "1111aaaa-name",
|
||||||
DedicatedIPs: []netip.Addr{netip.MustParseAddr("1.1.1.2")},
|
DedicatedIPs: []netip.Addr{netip.MustParseAddr("1.1.1.2")},
|
||||||
FilteringEnabled: false,
|
FilteringEnabled: false,
|
||||||
}, {
|
}, {
|
||||||
ID: "b9e1a762",
|
Auth: &agd.AuthSettings{
|
||||||
|
Enabled: true,
|
||||||
|
DoHAuthOnly: true,
|
||||||
|
PasswordHash: agdpasswd.NewPasswordHashBcrypt([]byte("test-hash")),
|
||||||
|
},
|
||||||
|
ID: "2222bbbb",
|
||||||
LinkedIP: netip.MustParseAddr("2.2.2.2"),
|
LinkedIP: netip.MustParseAddr("2.2.2.2"),
|
||||||
Name: "b9e1a762-name",
|
Name: "2222bbbb-name",
|
||||||
DedicatedIPs: nil,
|
DedicatedIPs: nil,
|
||||||
FilteringEnabled: true,
|
FilteringEnabled: true,
|
||||||
|
}, {
|
||||||
|
Auth: &agd.AuthSettings{
|
||||||
|
Enabled: true,
|
||||||
|
DoHAuthOnly: false,
|
||||||
|
PasswordHash: agdpasswd.AllowAuthenticator{},
|
||||||
|
},
|
||||||
|
ID: "3333cccc",
|
||||||
|
LinkedIP: netip.MustParseAddr("3.3.3.3"),
|
||||||
|
Name: "3333cccc-name",
|
||||||
|
DedicatedIPs: nil,
|
||||||
|
FilteringEnabled: false,
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +528,7 @@ func BenchmarkDNSProfile_ToInternal(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
profSink, _, errSink = dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
profSink, _, errSink = dp.toInternal(ctx, TestUpdTime, testBind, errColl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ func BenchmarkProfileStorage_Profiles(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
respSink, errSink = s.Profiles(ctx, req)
|
respSink, errSink = s.Profiles(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@ package billstat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
@ -18,6 +18,9 @@ import (
|
|||||||
// RuntimeRecorderConfig is the configuration structure for a runtime billing
|
// RuntimeRecorderConfig is the configuration structure for a runtime billing
|
||||||
// statistics recorder. All fields must be non-empty.
|
// statistics recorder. All fields must be non-empty.
|
||||||
type RuntimeRecorderConfig struct {
|
type RuntimeRecorderConfig struct {
|
||||||
|
// ErrColl is used to collect errors during refreshes.
|
||||||
|
ErrColl errcoll.Interface
|
||||||
|
|
||||||
// Uploader is used to upload the billing statistics records to.
|
// Uploader is used to upload the billing statistics records to.
|
||||||
Uploader Uploader
|
Uploader Uploader
|
||||||
}
|
}
|
||||||
@ -29,6 +32,7 @@ func NewRuntimeRecorder(c *RuntimeRecorderConfig) (r *RuntimeRecorder) {
|
|||||||
mu: &sync.Mutex{},
|
mu: &sync.Mutex{},
|
||||||
records: Records{},
|
records: Records{},
|
||||||
uploader: c.Uploader,
|
uploader: c.Uploader,
|
||||||
|
errColl: c.ErrColl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +48,9 @@ type RuntimeRecorder struct {
|
|||||||
// uploader is the uploader to which the billing statistics records are
|
// uploader is the uploader to which the billing statistics records are
|
||||||
// uploaded.
|
// uploaded.
|
||||||
uploader Uploader
|
uploader Uploader
|
||||||
|
|
||||||
|
// errColl is used to collect errors during refreshes.
|
||||||
|
errColl errcoll.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
@ -58,6 +65,10 @@ func (r *RuntimeRecorder) Record(
|
|||||||
start time.Time,
|
start time.Time,
|
||||||
proto agd.Protocol,
|
proto agd.Protocol,
|
||||||
) {
|
) {
|
||||||
|
// TODO(a.garipov): Use slog.
|
||||||
|
log.Debug("billstat_refresh: started")
|
||||||
|
defer log.Debug("billstat_refresh: finished")
|
||||||
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
@ -96,7 +107,7 @@ func (r *RuntimeRecorder) Refresh(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.remergeRecords(records)
|
r.remergeRecords(records)
|
||||||
log.Info("billstat: refresh failed, records remerged")
|
log.Info("billstat_refresh: failed, records remerged")
|
||||||
} else {
|
} else {
|
||||||
metrics.BillStatUploadTimestamp.SetToCurrentTime()
|
metrics.BillStatUploadTimestamp.SetToCurrentTime()
|
||||||
}
|
}
|
||||||
@ -106,10 +117,10 @@ func (r *RuntimeRecorder) Refresh(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
err = r.uploader.Upload(ctx, records)
|
err = r.uploader.Upload(ctx, records)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("uploading billstat records: %w", err)
|
errcoll.Collectf(ctx, r.errColl, "billstat_refresh: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetRecords returns the current data and resets the records map to an empty
|
// resetRecords returns the current data and resets the records map to an empty
|
||||||
|
@ -30,6 +30,11 @@ const (
|
|||||||
func TestRuntimeRecorder_success(t *testing.T) {
|
func TestRuntimeRecorder_success(t *testing.T) {
|
||||||
var gotRecord *billstat.Record
|
var gotRecord *billstat.Record
|
||||||
c := &billstat.RuntimeRecorderConfig{
|
c := &billstat.RuntimeRecorderConfig{
|
||||||
|
ErrColl: &agdtest.ErrorCollector{
|
||||||
|
OnCollect: func(_ context.Context, _ error) {
|
||||||
|
panic("not implemented")
|
||||||
|
},
|
||||||
|
},
|
||||||
Uploader: &agdtest.BillStatUploader{
|
Uploader: &agdtest.BillStatUploader{
|
||||||
OnUpload: func(_ context.Context, records billstat.Records) (err error) {
|
OnUpload: func(_ context.Context, records billstat.Records) (err error) {
|
||||||
gotRecord = records[devID]
|
gotRecord = records[devID]
|
||||||
@ -48,7 +53,7 @@ func TestRuntimeRecorder_success(t *testing.T) {
|
|||||||
// incremented.
|
// incremented.
|
||||||
const reqNum = 2
|
const reqNum = 2
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < reqNum; i++ {
|
for range reqNum {
|
||||||
r.Record(ctx, devID, clientCtry, clientASN, start, proto)
|
r.Record(ctx, devID, clientCtry, clientASN, start, proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +94,13 @@ func TestRuntimeRecorder_fail(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gotCollErr error
|
||||||
c := &billstat.RuntimeRecorderConfig{
|
c := &billstat.RuntimeRecorderConfig{
|
||||||
|
ErrColl: &agdtest.ErrorCollector{
|
||||||
|
OnCollect: func(_ context.Context, err error) {
|
||||||
|
gotCollErr = err
|
||||||
|
},
|
||||||
|
},
|
||||||
Uploader: &agdtest.BillStatUploader{
|
Uploader: &agdtest.BillStatUploader{
|
||||||
OnUpload: onUpload,
|
OnUpload: onUpload,
|
||||||
},
|
},
|
||||||
@ -118,6 +129,7 @@ func TestRuntimeRecorder_fail(t *testing.T) {
|
|||||||
|
|
||||||
err := r.Refresh(context.Background())
|
err := r.Refresh(context.Background())
|
||||||
require.ErrorIs(t, err, testError)
|
require.ErrorIs(t, err, testError)
|
||||||
|
require.ErrorIs(t, gotCollErr, testError)
|
||||||
require.Nil(t, gotRecord)
|
require.Nil(t, gotRecord)
|
||||||
|
|
||||||
// Request the backend again, expect the correct, merged data.
|
// Request the backend again, expect the correct, merged data.
|
||||||
|
@ -46,6 +46,7 @@ func newChanPacketConn(
|
|||||||
sessions chan *packetSession,
|
sessions chan *packetSession,
|
||||||
subnet netip.Prefix,
|
subnet netip.Prefix,
|
||||||
writeRequests chan *packetConnWriteReq,
|
writeRequests chan *packetConnWriteReq,
|
||||||
|
writeRequestsGauge prometheus.Gauge,
|
||||||
laddr net.Addr,
|
laddr net.Addr,
|
||||||
) (c *chanPacketConn) {
|
) (c *chanPacketConn) {
|
||||||
return &chanPacketConn{
|
return &chanPacketConn{
|
||||||
@ -54,7 +55,7 @@ func newChanPacketConn(
|
|||||||
writeRequests: writeRequests,
|
writeRequests: writeRequests,
|
||||||
|
|
||||||
sessionsGauge: metrics.BindToDeviceUDPSessionsChanSize.WithLabelValues(subnet.String()),
|
sessionsGauge: metrics.BindToDeviceUDPSessionsChanSize.WithLabelValues(subnet.String()),
|
||||||
writeRequestsGauge: metrics.BindToDeviceUDPWriteRequestsChanSize.WithLabelValues(subnet.String()),
|
writeRequestsGauge: writeRequestsGauge,
|
||||||
|
|
||||||
deadlineMu: &sync.RWMutex{},
|
deadlineMu: &sync.RWMutex{},
|
||||||
|
|
||||||
@ -64,9 +65,9 @@ func newChanPacketConn(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// packetConnWriteReq is a request to write a piece of data to the original
|
// packetConnWriteReq is a request to write a piece of data to the original
|
||||||
// packet connection. resp, body, and either raddr or session must be set.
|
// packet connection. respCh, body, and either raddr or session must be set.
|
||||||
type packetConnWriteReq struct {
|
type packetConnWriteReq struct {
|
||||||
resp chan *packetConnWriteResp
|
respCh chan *packetConnWriteResp
|
||||||
session *packetSession
|
session *packetSession
|
||||||
raddr net.Addr
|
raddr net.Addr
|
||||||
deadline time.Time
|
deadline time.Time
|
||||||
@ -265,7 +266,7 @@ func (c *chanPacketConn) writeToSession(
|
|||||||
|
|
||||||
resp := make(chan *packetConnWriteResp, 1)
|
resp := make(chan *packetConnWriteResp, 1)
|
||||||
req := &packetConnWriteReq{
|
req := &packetConnWriteReq{
|
||||||
resp: resp,
|
respCh: resp,
|
||||||
session: s,
|
session: s,
|
||||||
raddr: raddr,
|
raddr: raddr,
|
||||||
deadline: deadline,
|
deadline: deadline,
|
||||||
|
@ -8,13 +8,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestChanPacketConn_Close(t *testing.T) {
|
func TestChanPacketConn_Close(t *testing.T) {
|
||||||
sessions := make(chan *packetSession)
|
sessions := make(chan *packetSession)
|
||||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, testLAddr)
|
c := newChanPacketConn(sessions, testSubnetIPv4, nil, nil, testLAddr)
|
||||||
err := c.Close()
|
err := c.Close()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -23,14 +24,14 @@ func TestChanPacketConn_Close(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChanPacketConn_LocalAddr(t *testing.T) {
|
func TestChanPacketConn_LocalAddr(t *testing.T) {
|
||||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
c := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||||
got := c.LocalAddr()
|
got := c.LocalAddr()
|
||||||
assert.Equal(t, testLAddr, got)
|
assert.Equal(t, testLAddr, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChanPacketConn_ReadFromSession(t *testing.T) {
|
func TestChanPacketConn_ReadFromSession(t *testing.T) {
|
||||||
sessions := make(chan *packetSession, 1)
|
sessions := make(chan *packetSession, 1)
|
||||||
c := newChanPacketConn(sessions, testSubnetIPv4, nil, testLAddr)
|
c := newChanPacketConn(sessions, testSubnetIPv4, nil, nil, testLAddr)
|
||||||
|
|
||||||
body := []byte("hello")
|
body := []byte("hello")
|
||||||
bodyLen := len(body)
|
bodyLen := len(body)
|
||||||
@ -79,7 +80,9 @@ func TestChanPacketConn_ReadFromSession(t *testing.T) {
|
|||||||
func TestChanPacketConn_WriteToSession(t *testing.T) {
|
func TestChanPacketConn_WriteToSession(t *testing.T) {
|
||||||
sessions := make(chan *packetSession, 1)
|
sessions := make(chan *packetSession, 1)
|
||||||
writes := make(chan *packetConnWriteReq, 1)
|
writes := make(chan *packetConnWriteReq, 1)
|
||||||
c := newChanPacketConn(sessions, testSubnetIPv4, writes, testLAddr)
|
|
||||||
|
gauge := prometheus.NewGauge(prometheus.GaugeOpts{})
|
||||||
|
c := newChanPacketConn(sessions, testSubnetIPv4, writes, gauge, testLAddr)
|
||||||
|
|
||||||
body := []byte("hello")
|
body := []byte("hello")
|
||||||
bodyLen := len(body)
|
bodyLen := len(body)
|
||||||
@ -125,7 +128,7 @@ func checkWriteReqAndRespond(
|
|||||||
|
|
||||||
req, ok := testutil.RequireReceive(pt, writes, testTimeout)
|
req, ok := testutil.RequireReceive(pt, writes, testTimeout)
|
||||||
require.NotNil(pt, req)
|
require.NotNil(pt, req)
|
||||||
require.NotNil(pt, req.resp)
|
require.NotNil(pt, req.respCh)
|
||||||
require.True(pt, ok)
|
require.True(pt, ok)
|
||||||
|
|
||||||
if wantRaddr != nil {
|
if wantRaddr != nil {
|
||||||
@ -141,14 +144,14 @@ func checkWriteReqAndRespond(
|
|||||||
assert.Equal(pt, wantDeadline, req.deadline)
|
assert.Equal(pt, wantDeadline, req.deadline)
|
||||||
assert.Equal(pt, wantBody, req.body)
|
assert.Equal(pt, wantBody, req.body)
|
||||||
|
|
||||||
testutil.RequireSend(pt, req.resp, &packetConnWriteResp{
|
testutil.RequireSend(pt, req.respCh, &packetConnWriteResp{
|
||||||
err: nil,
|
err: nil,
|
||||||
written: len(wantBody),
|
written: len(wantBody),
|
||||||
}, testTimeout)
|
}, testTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChanPacketConn_deadlines(t *testing.T) {
|
func TestChanPacketConn_deadlines(t *testing.T) {
|
||||||
c := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
c := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||||
deadline := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
|
deadline := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
@ -15,19 +15,22 @@ import (
|
|||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/syncutil"
|
"github.com/AdguardTeam/golibs/syncutil"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// interfaceListener contains information about a single interface listener.
|
// interfaceListener contains information about a single interface listener.
|
||||||
type interfaceListener struct {
|
type interfaceListener struct {
|
||||||
conns *connIndex
|
conns *connIndex
|
||||||
listenConf *net.ListenConfig
|
listenConf *net.ListenConfig
|
||||||
bodyPool *syncutil.Pool[[]byte]
|
bodyPool *syncutil.Pool[[]byte]
|
||||||
oobPool *syncutil.Pool[[]byte]
|
oobPool *syncutil.Pool[[]byte]
|
||||||
writeRequests chan *packetConnWriteReq
|
writeRequests chan *packetConnWriteReq
|
||||||
done chan unit
|
done chan unit
|
||||||
errColl errcoll.Interface
|
errColl errcoll.Interface
|
||||||
ifaceName string
|
writeRequestsGauge prometheus.Gauge
|
||||||
port uint16
|
writeDurationHist prometheus.Observer
|
||||||
|
ifaceName string
|
||||||
|
port uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// listenTCP runs the TCP listening loop. It is intended to be used as a
|
// listenTCP runs the TCP listening loop. It is intended to be used as a
|
||||||
@ -113,7 +116,7 @@ func (l *interfaceListener) listenUDP(errCh chan<- error) {
|
|||||||
|
|
||||||
errCh <- nil
|
errCh <- nil
|
||||||
|
|
||||||
go l.writeUDP(udpConn)
|
go l.writeUDPResponses(udpConn)
|
||||||
|
|
||||||
logPrefix := fmt.Sprintf("bindtodevice: listener %s:%d: udp", l.ifaceName, l.port)
|
logPrefix := fmt.Sprintf("bindtodevice: listener %s:%d: udp", l.ifaceName, l.port)
|
||||||
|
|
||||||
@ -185,46 +188,60 @@ func (l *interfaceListener) readUDP(c *net.UDPConn, logPrefix string) (err error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeUDP runs the UDP write loop. It is intended to be used as a goroutine.
|
// writeUDPResponses runs the UDP write loop. It is intended to be used as a
|
||||||
func (l *interfaceListener) writeUDP(c *net.UDPConn) {
|
// goroutine.
|
||||||
|
func (l *interfaceListener) writeUDPResponses(c *net.UDPConn) {
|
||||||
defer log.OnPanic("interfaceListener.writeUDP")
|
defer log.OnPanic("interfaceListener.writeUDP")
|
||||||
|
|
||||||
logPrefix := fmt.Sprintf("bindtodevice: listener %s:%d: udp write", l.ifaceName, l.port)
|
|
||||||
for {
|
for {
|
||||||
var req *packetConnWriteReq
|
|
||||||
select {
|
select {
|
||||||
case <-l.done:
|
case <-l.done:
|
||||||
optlog.Debug1("%s: done", logPrefix)
|
optlog.Debug2("bindtodevice: listener %s:%d: udp write: done", l.ifaceName, l.port)
|
||||||
|
|
||||||
return
|
return
|
||||||
case req = <-l.writeRequests:
|
case req := <-l.writeRequests:
|
||||||
// Go on.
|
l.writeUDP(c, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &packetConnWriteResp{}
|
|
||||||
resp.err = c.SetWriteDeadline(req.deadline)
|
|
||||||
if resp.err != nil {
|
|
||||||
req.resp <- resp
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if s := req.session; s == nil {
|
|
||||||
resp.written, resp.err = c.WriteTo(req.body, req.raddr)
|
|
||||||
} else {
|
|
||||||
resp.written, _, resp.err = c.WriteMsgUDP(
|
|
||||||
req.body,
|
|
||||||
s.respOOB,
|
|
||||||
req.session.raddr,
|
|
||||||
)
|
|
||||||
|
|
||||||
l.bodyPool.Put(&s.readBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
resetDeadlineErr := c.SetWriteDeadline(time.Time{})
|
|
||||||
|
|
||||||
resp.err = errors.WithDeferred(resp.err, resetDeadlineErr)
|
|
||||||
|
|
||||||
req.resp <- resp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeUDP handles a single write operation and writes a response to
|
||||||
|
// req.respCh.
|
||||||
|
func (l *interfaceListener) writeUDP(c *net.UDPConn, req *packetConnWriteReq) {
|
||||||
|
resp := &packetConnWriteResp{}
|
||||||
|
resp.err = c.SetWriteDeadline(req.deadline)
|
||||||
|
if resp.err != nil {
|
||||||
|
req.respCh <- resp
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.writeToUDPConn(c, req, resp)
|
||||||
|
|
||||||
|
resetDeadlineErr := c.SetWriteDeadline(time.Time{})
|
||||||
|
resp.err = errors.WithDeferred(resp.err, resetDeadlineErr)
|
||||||
|
|
||||||
|
req.respCh <- resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeToUDPConn writes to c, depending on what kind of session req contains,
|
||||||
|
// and sets resp.written and resp.err accordingly.
|
||||||
|
func (l *interfaceListener) writeToUDPConn(
|
||||||
|
c *net.UDPConn,
|
||||||
|
req *packetConnWriteReq,
|
||||||
|
resp *packetConnWriteResp,
|
||||||
|
) {
|
||||||
|
start := time.Now()
|
||||||
|
defer func() { l.writeDurationHist.Observe(time.Since(start).Seconds()) }()
|
||||||
|
|
||||||
|
s := req.session
|
||||||
|
if s == nil {
|
||||||
|
resp.written, resp.err = c.WriteTo(req.body, req.raddr)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.written, _, resp.err = c.WriteMsgUDP(req.body, s.respOOB, req.session.raddr)
|
||||||
|
|
||||||
|
l.bodyPool.Put(&s.readBody)
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestListenConfig(t *testing.T) {
|
func TestListenConfig(t *testing.T) {
|
||||||
pc := newChanPacketConn(nil, testSubnetIPv4, nil, testLAddr)
|
pc := newChanPacketConn(nil, testSubnetIPv4, nil, nil, testLAddr)
|
||||||
lsnr := newChanListener(nil, testSubnetIPv4, testLAddr)
|
lsnr := newChanListener(nil, testSubnetIPv4, testLAddr)
|
||||||
addr := &agdnet.PrefixNetAddr{
|
addr := &agdnet.PrefixNetAddr{
|
||||||
Prefix: testSubnetIPv4,
|
Prefix: testSubnetIPv4,
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/netext"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/netext"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/mapsutil"
|
"github.com/AdguardTeam/golibs/mapsutil"
|
||||||
@ -84,7 +85,7 @@ func (m *Manager) Add(id ID, ifaceName string, port uint16, ctrlConf *ControlCon
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mapsutil.OrderedRangeError(m.ifaceListeners, validateDup)
|
err = mapsutil.SortedRangeError(m.ifaceListeners, validateDup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return err
|
return err
|
||||||
@ -109,15 +110,17 @@ func (m *Manager) newInterfaceListener(
|
|||||||
port uint16,
|
port uint16,
|
||||||
) (l *interfaceListener) {
|
) (l *interfaceListener) {
|
||||||
return &interfaceListener{
|
return &interfaceListener{
|
||||||
conns: &connIndex{},
|
conns: &connIndex{},
|
||||||
listenConf: newListenConfig(ifaceName, ctrlConf),
|
listenConf: newListenConfig(ifaceName, ctrlConf),
|
||||||
bodyPool: syncutil.NewSlicePool[byte](bodySize),
|
bodyPool: syncutil.NewSlicePool[byte](bodySize),
|
||||||
oobPool: syncutil.NewSlicePool[byte](netext.IPDstOOBSize),
|
oobPool: syncutil.NewSlicePool[byte](netext.IPDstOOBSize),
|
||||||
writeRequests: make(chan *packetConnWriteReq, m.chanBufSize),
|
writeRequests: make(chan *packetConnWriteReq, m.chanBufSize),
|
||||||
done: m.done,
|
done: m.done,
|
||||||
errColl: m.errColl,
|
errColl: m.errColl,
|
||||||
ifaceName: ifaceName,
|
writeRequestsGauge: metrics.BindToDeviceUDPWriteRequestsChanSize.WithLabelValues(ifaceName),
|
||||||
port: port,
|
writeDurationHist: metrics.BindToDeviceUDPWriteDurationSeconds.WithLabelValues(ifaceName),
|
||||||
|
ifaceName: ifaceName,
|
||||||
|
port: port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,11 +162,17 @@ func (m *Manager) ListenConfig(id ID, subnet netip.Prefix) (c *ListenConfig, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessCh := make(chan *packetSession, m.chanBufSize)
|
sessCh := make(chan *packetSession, m.chanBufSize)
|
||||||
pConn := newChanPacketConn(sessCh, subnet, l.writeRequests, &agdnet.PrefixNetAddr{
|
pConn := newChanPacketConn(
|
||||||
Prefix: subnet,
|
sessCh,
|
||||||
Net: "udp",
|
subnet,
|
||||||
Port: l.port,
|
l.writeRequests,
|
||||||
})
|
l.writeRequestsGauge,
|
||||||
|
&agdnet.PrefixNetAddr{
|
||||||
|
Prefix: subnet,
|
||||||
|
Net: "udp",
|
||||||
|
Port: l.port,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
err = l.conns.addPacketConn(pConn)
|
err = l.conns.addPacketConn(pConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -233,10 +233,10 @@ func TestManager(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, lc)
|
require.NotNil(t, lc)
|
||||||
|
|
||||||
err = m.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err = m.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||||
return m.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
return m.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("tcp", func(t *testing.T) {
|
t.Run("tcp", func(t *testing.T) {
|
||||||
|
@ -113,9 +113,7 @@ func SubtestListenControlTCP(
|
|||||||
ifaceName string,
|
ifaceName string,
|
||||||
ifaceNet *net.IPNet,
|
ifaceNet *net.IPNet,
|
||||||
) {
|
) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||||
t.Cleanup(cancel)
|
|
||||||
|
|
||||||
lsnr, err := lc.Listen(ctx, "tcp", "0.0.0.0:0")
|
lsnr, err := lc.Listen(ctx, "tcp", "0.0.0.0:0")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, lsnr.Close)
|
testutil.CleanupAndRequireSuccess(t, lsnr.Close)
|
||||||
@ -194,9 +192,7 @@ func SubtestListenControlUDP(
|
|||||||
ifaceName string,
|
ifaceName string,
|
||||||
ifaceNet *net.IPNet,
|
ifaceNet *net.IPNet,
|
||||||
) {
|
) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||||
t.Cleanup(cancel)
|
|
||||||
|
|
||||||
packetConn, err := lc.ListenPacket(ctx, "udp", "0.0.0.0:0")
|
packetConn, err := lc.ListenPacket(ctx, "udp", "0.0.0.0:0")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, packetConn.Close)
|
testutil.CleanupAndRequireSuccess(t, packetConn.Close)
|
||||||
@ -528,7 +524,7 @@ func BenchmarkReadPacketSession(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
sessSink, errSink = readPacketSession(c, body, oob)
|
sessSink, errSink = readPacketSession(c, body, oob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ type additionalInfo map[string]string
|
|||||||
|
|
||||||
// validateAdditionalInfo return an error is the section is invalid.
|
// validateAdditionalInfo return an error is the section is invalid.
|
||||||
func (c additionalInfo) validate() (err error) {
|
func (c additionalInfo) validate() (err error) {
|
||||||
return mapsutil.OrderedRangeError(c, func(k, _ string) (keyErr error) {
|
return mapsutil.SortedRangeError(c, func(k, _ string) (keyErr error) {
|
||||||
if model.LabelName(k).IsValid() {
|
if model.LabelName(k).IsValid() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ func setupBillStat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rec = billstat.NewRuntimeRecorder(&billstat.RuntimeRecorderConfig{
|
rec = billstat.NewRuntimeRecorder(&billstat.RuntimeRecorderConfig{
|
||||||
|
ErrColl: errColl,
|
||||||
Uploader: billStatUploader,
|
Uploader: billStatUploader,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -120,13 +121,11 @@ func setupBillStat(
|
|||||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||||
return context.WithTimeout(context.Background(), timeout)
|
return context.WithTimeout(context.Background(), timeout)
|
||||||
},
|
},
|
||||||
Refresher: rec,
|
Refresher: rec,
|
||||||
ErrColl: errColl,
|
Name: "billstat",
|
||||||
Name: "billstat",
|
Interval: refrIvl,
|
||||||
Interval: refrIvl,
|
RefreshOnShutdown: true,
|
||||||
RefreshOnShutdown: true,
|
RandomizeStart: false,
|
||||||
RoutineLogsAreDebug: true,
|
|
||||||
RandomizeStart: false,
|
|
||||||
})
|
})
|
||||||
err = billStatRefr.Start(context.Background())
|
err = billStatRefr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -157,6 +156,7 @@ func setupProfDB(
|
|||||||
timeout := conf.Timeout.Duration
|
timeout := conf.Timeout.Duration
|
||||||
profDB, err = profiledb.New(&profiledb.Config{
|
profDB, err = profiledb.New(&profiledb.Config{
|
||||||
Storage: profStrg,
|
Storage: profStrg,
|
||||||
|
ErrColl: errColl,
|
||||||
FullSyncIvl: conf.FullRefreshIvl.Duration,
|
FullSyncIvl: conf.FullRefreshIvl.Duration,
|
||||||
FullSyncRetryIvl: conf.FullRefreshRetryIvl.Duration,
|
FullSyncRetryIvl: conf.FullRefreshRetryIvl.Duration,
|
||||||
InitialTimeout: timeout,
|
InitialTimeout: timeout,
|
||||||
@ -172,13 +172,11 @@ func setupProfDB(
|
|||||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||||
return context.WithTimeout(context.Background(), timeout)
|
return context.WithTimeout(context.Background(), timeout)
|
||||||
},
|
},
|
||||||
Refresher: profDB,
|
Refresher: profDB,
|
||||||
ErrColl: errColl,
|
Name: "profiledb",
|
||||||
Name: "profiledb",
|
Interval: refrIvl,
|
||||||
Interval: refrIvl,
|
RefreshOnShutdown: false,
|
||||||
RefreshOnShutdown: false,
|
RandomizeStart: true,
|
||||||
RoutineLogsAreDebug: true,
|
|
||||||
RandomizeStart: true,
|
|
||||||
})
|
})
|
||||||
err = profDBRefr.Start(context.Background())
|
err = profDBRefr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
"github.com/AdguardTeam/AdGuardDNS/internal/access"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnscheck"
|
||||||
@ -27,7 +26,6 @@ import (
|
|||||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/service"
|
"github.com/AdguardTeam/golibs/service"
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Main is the entry point of application.
|
// Main is the entry point of application.
|
||||||
@ -92,9 +90,6 @@ func Main() {
|
|||||||
|
|
||||||
// Safe-browsing and adult-blocking filters
|
// Safe-browsing and adult-blocking filters
|
||||||
|
|
||||||
// TODO(ameshkov): Consider making configurable.
|
|
||||||
filteringResolver := agdnet.NewCachingResolver(agdnet.DefaultResolver{}, 1*timeutil.Day)
|
|
||||||
|
|
||||||
err = os.MkdirAll(envs.FilterCachePath, agd.DefaultDirPerm)
|
err = os.MkdirAll(envs.FilterCachePath, agd.DefaultDirPerm)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
@ -105,7 +100,6 @@ func Main() {
|
|||||||
cloner := dnsmsg.NewCloner(metrics.ClonerStat{})
|
cloner := dnsmsg.NewCloner(metrics.ClonerStat{})
|
||||||
safeBrowsingHashes, safeBrowsingFilter, err := setupHashPrefixFilter(
|
safeBrowsingHashes, safeBrowsingFilter, err := setupHashPrefixFilter(
|
||||||
c.SafeBrowsing,
|
c.SafeBrowsing,
|
||||||
filteringResolver,
|
|
||||||
cloner,
|
cloner,
|
||||||
agd.FilterListIDSafeBrowsing,
|
agd.FilterListIDSafeBrowsing,
|
||||||
envs.SafeBrowsingURL,
|
envs.SafeBrowsingURL,
|
||||||
@ -118,7 +112,6 @@ func Main() {
|
|||||||
|
|
||||||
adultBlockingHashes, adultBlockingFilter, err := setupHashPrefixFilter(
|
adultBlockingHashes, adultBlockingFilter, err := setupHashPrefixFilter(
|
||||||
c.AdultBlocking,
|
c.AdultBlocking,
|
||||||
filteringResolver,
|
|
||||||
cloner,
|
cloner,
|
||||||
agd.FilterListIDAdultBlocking,
|
agd.FilterListIDAdultBlocking,
|
||||||
envs.AdultBlockingURL,
|
envs.AdultBlockingURL,
|
||||||
@ -132,7 +125,6 @@ func Main() {
|
|||||||
_, newRegDomainsFilter, err := setupHashPrefixFilter(
|
_, newRegDomainsFilter, err := setupHashPrefixFilter(
|
||||||
// Reuse general safe browsing filter configuration.
|
// Reuse general safe browsing filter configuration.
|
||||||
c.SafeBrowsing,
|
c.SafeBrowsing,
|
||||||
filteringResolver,
|
|
||||||
cloner,
|
cloner,
|
||||||
agd.FilterListIDNewRegDomains,
|
agd.FilterListIDNewRegDomains,
|
||||||
envs.NewRegDomainsURL,
|
envs.NewRegDomainsURL,
|
||||||
@ -147,8 +139,6 @@ func Main() {
|
|||||||
|
|
||||||
fltStrgConf := c.Filters.toInternal(
|
fltStrgConf := c.Filters.toInternal(
|
||||||
errColl,
|
errColl,
|
||||||
filteringResolver,
|
|
||||||
cloner,
|
|
||||||
envs,
|
envs,
|
||||||
safeBrowsingFilter,
|
safeBrowsingFilter,
|
||||||
adultBlockingFilter,
|
adultBlockingFilter,
|
||||||
@ -156,7 +146,7 @@ func Main() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fltRefrTimeout := c.Filters.RefreshTimeout.Duration
|
fltRefrTimeout := c.Filters.RefreshTimeout.Duration
|
||||||
fltStrg, err := setupFilterStorage(fltStrgConf, sigHdlr, errColl, fltRefrTimeout)
|
fltStrg, err := setupFilterStorage(fltStrgConf, sigHdlr, fltRefrTimeout)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
fltGroups, err := c.FilteringGroups.toInternal(fltStrg)
|
fltGroups, err := c.FilteringGroups.toInternal(fltStrg)
|
||||||
@ -293,8 +283,6 @@ func Main() {
|
|||||||
UseCacheTTLOverride: c.Cache.TTLOverride.Enabled,
|
UseCacheTTLOverride: c.Cache.TTLOverride.Enabled,
|
||||||
UseECSCache: c.Cache.Type == cacheTypeECS,
|
UseECSCache: c.Cache.Type == cacheTypeECS,
|
||||||
ProfileDBEnabled: bool(envs.ProfilesEnabled),
|
ProfileDBEnabled: bool(envs.ProfilesEnabled),
|
||||||
ResearchMetrics: bool(envs.ResearchMetrics),
|
|
||||||
ResearchLogs: bool(envs.ResearchLogs),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsSvc, err := dnssvc.New(dnsConf)
|
dnsSvc, err := dnssvc.New(dnsConf)
|
||||||
|
@ -100,7 +100,8 @@ func (c *configuration) buildQueryLog(envs *environments) (l querylog.Interface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return querylog.NewFileSystem(&querylog.FileSystemConfig{
|
return querylog.NewFileSystem(&querylog.FileSystemConfig{
|
||||||
Path: envs.QueryLogPath,
|
Path: envs.QueryLogPath,
|
||||||
|
RandSeed: uint64(time.Now().UnixNano()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,8 +50,8 @@ func (c *ddrConfig) toInternal(msgs *dnsmsg.Constructor) (conf *agd.DDR) {
|
|||||||
func ddrRecsToSVCBTmpls(
|
func ddrRecsToSVCBTmpls(
|
||||||
msgs *dnsmsg.Constructor,
|
msgs *dnsmsg.Constructor,
|
||||||
records map[string]*ddrRecord,
|
records map[string]*ddrRecord,
|
||||||
) (targets *stringutil.Set, tmpls []*dns.SVCB) {
|
) (targets *container.MapSet[string], tmpls []*dns.SVCB) {
|
||||||
targets = stringutil.NewSet()
|
targets = container.NewMapSet[string]()
|
||||||
for target, r := range records {
|
for target, r := range records {
|
||||||
target = strings.TrimPrefix(target, "*.")
|
target = strings.TrimPrefix(target, "*.")
|
||||||
targets.Add(target)
|
targets.Add(target)
|
||||||
|
@ -60,8 +60,6 @@ type environments struct {
|
|||||||
LogTimestamp strictBool `env:"LOG_TIMESTAMP" envDefault:"1"`
|
LogTimestamp strictBool `env:"LOG_TIMESTAMP" envDefault:"1"`
|
||||||
LogVerbose strictBool `env:"VERBOSE" envDefault:"0"`
|
LogVerbose strictBool `env:"VERBOSE" envDefault:"0"`
|
||||||
ProfilesEnabled strictBool `env:"PROFILES_ENABLED" envDefault:"1"`
|
ProfilesEnabled strictBool `env:"PROFILES_ENABLED" envDefault:"1"`
|
||||||
ResearchMetrics strictBool `env:"RESEARCH_METRICS" envDefault:"0"`
|
|
||||||
ResearchLogs strictBool `env:"RESEARCH_LOGS" envDefault:"0"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// readEnvs reads the configuration.
|
// readEnvs reads the configuration.
|
||||||
@ -117,9 +115,7 @@ func (envs *environments) buildErrColl() (errColl errcoll.Interface, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// geoIP returns an GeoIP database implementation from environment.
|
// geoIP returns an GeoIP database implementation from environment.
|
||||||
func (envs *environments) geoIP(
|
func (envs *environments) geoIP(c *geoIPConfig) (g *geoip.File, err error) {
|
||||||
c *geoIPConfig,
|
|
||||||
) (g *geoip.File, err error) {
|
|
||||||
log.Debug("using geoip files %q and %q", envs.GeoIPASNPath, envs.GeoIPCountryPath)
|
log.Debug("using geoip files %q and %q", envs.GeoIPASNPath, envs.GeoIPCountryPath)
|
||||||
|
|
||||||
g, err = geoip.NewFile(&geoip.FileConfig{
|
g, err = geoip.NewFile(&geoip.FileConfig{
|
||||||
@ -180,19 +176,18 @@ func (envs *environments) buildRuleStat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
httpRuleStat := rulestat.NewHTTP(&rulestat.HTTPConfig{
|
httpRuleStat := rulestat.NewHTTP(&rulestat.HTTPConfig{
|
||||||
URL: &envs.RuleStatURL.URL,
|
ErrColl: errColl,
|
||||||
|
URL: &envs.RuleStatURL.URL,
|
||||||
})
|
})
|
||||||
|
|
||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: ctxWithDefaultTimeout,
|
Context: ctxWithDefaultTimeout,
|
||||||
Refresher: httpRuleStat,
|
Refresher: httpRuleStat,
|
||||||
ErrColl: errColl,
|
|
||||||
Name: "rulestat",
|
Name: "rulestat",
|
||||||
// TODO(ameshkov): Consider making configurable.
|
// TODO(ameshkov): Consider making configurable.
|
||||||
Interval: 10 * time.Minute,
|
Interval: 10 * time.Minute,
|
||||||
RefreshOnShutdown: true,
|
RefreshOnShutdown: true,
|
||||||
RoutineLogsAreDebug: false,
|
RandomizeStart: false,
|
||||||
RandomizeStart: false,
|
|
||||||
})
|
})
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,24 +16,6 @@ func check(err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// coalesceError returns the first non-nil error. It is named after function
|
|
||||||
// COALESCE in SQL. If all errors are nil, it returns nil.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Consider a similar helper to group errors together to show
|
|
||||||
// as many errors as possible.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Think of ways to merge with [aghalg.Coalesce] in AdGuard
|
|
||||||
// Home.
|
|
||||||
func coalesceError(errors ...error) (res error) {
|
|
||||||
for _, err := range errors {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// numberOrDuration is the constraint for integer types along with
|
// numberOrDuration is the constraint for integer types along with
|
||||||
// timeutil.Duration.
|
// timeutil.Duration.
|
||||||
type numberOrDuration interface {
|
type numberOrDuration interface {
|
||||||
|
@ -5,9 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter/hashprefix"
|
||||||
@ -17,10 +15,11 @@ import (
|
|||||||
"github.com/c2h5oh/datasize"
|
"github.com/c2h5oh/datasize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filters configuration
|
|
||||||
|
|
||||||
// filtersConfig contains the configuration for the filter lists and filtering
|
// filtersConfig contains the configuration for the filter lists and filtering
|
||||||
// storage to be used.
|
// storage to be used.
|
||||||
|
//
|
||||||
|
// TODO(a.garipov): Add the timeout for the blocked-service index refresh. It
|
||||||
|
// is currently hardcoded to 3 minutes.
|
||||||
type filtersConfig struct {
|
type filtersConfig struct {
|
||||||
// RuleListCache is the cache settings for the filtering rule-list.
|
// RuleListCache is the cache settings for the filtering rule-list.
|
||||||
RuleListCache *fltRuleListCache `yaml:"rule_list_cache"`
|
RuleListCache *fltRuleListCache `yaml:"rule_list_cache"`
|
||||||
@ -41,10 +40,21 @@ type filtersConfig struct {
|
|||||||
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
||||||
|
|
||||||
// RefreshTimeout is the timeout for the entire filter update operation.
|
// RefreshTimeout is the timeout for the entire filter update operation.
|
||||||
// Note that each individual refresh operation also has its own hardcoded
|
// Note that filter rule-list index and each filter rule-list update
|
||||||
// 30s timeout.
|
// operations have their own timeouts, see IndexRefreshTimeout and
|
||||||
|
// RuleListRefreshTimeout.
|
||||||
RefreshTimeout timeutil.Duration `yaml:"refresh_timeout"`
|
RefreshTimeout timeutil.Duration `yaml:"refresh_timeout"`
|
||||||
|
|
||||||
|
// IndexRefreshTimeout is the timeout for the filter rule-list index update
|
||||||
|
// operation. See also RefreshTimeout for the entire filter update
|
||||||
|
// operation.
|
||||||
|
IndexRefreshTimeout timeutil.Duration `yaml:"index_refresh_timeout"`
|
||||||
|
|
||||||
|
// RuleListRefreshTimeout is the timeout for the filter update operation of
|
||||||
|
// each rule-list, which includes safe-search filters. See also
|
||||||
|
// RefreshTimeout for the entire filter update operation.
|
||||||
|
RuleListRefreshTimeout timeutil.Duration `yaml:"rule_list_refresh_timeout"`
|
||||||
|
|
||||||
// MaxSize is the maximum size of the downloadable filtering rule-list.
|
// MaxSize is the maximum size of the downloadable filtering rule-list.
|
||||||
MaxSize datasize.ByteSize `yaml:"max_size"`
|
MaxSize datasize.ByteSize `yaml:"max_size"`
|
||||||
}
|
}
|
||||||
@ -53,8 +63,6 @@ type filtersConfig struct {
|
|||||||
// cacheDir must exist. c is assumed to be valid.
|
// cacheDir must exist. c is assumed to be valid.
|
||||||
func (c *filtersConfig) toInternal(
|
func (c *filtersConfig) toInternal(
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
resolver agdnet.Resolver,
|
|
||||||
cloner *dnsmsg.Cloner,
|
|
||||||
envs *environments,
|
envs *environments,
|
||||||
safeBrowsing *hashprefix.Filter,
|
safeBrowsing *hashprefix.Filter,
|
||||||
adultBlocking *hashprefix.Filter,
|
adultBlocking *hashprefix.Filter,
|
||||||
@ -70,17 +78,17 @@ func (c *filtersConfig) toInternal(
|
|||||||
NewRegDomains: newRegDomains,
|
NewRegDomains: newRegDomains,
|
||||||
Now: time.Now,
|
Now: time.Now,
|
||||||
ErrColl: errColl,
|
ErrColl: errColl,
|
||||||
Resolver: resolver,
|
|
||||||
Cloner: cloner,
|
|
||||||
CacheDir: envs.FilterCachePath,
|
CacheDir: envs.FilterCachePath,
|
||||||
CustomFilterCacheSize: c.CustomFilterCacheSize,
|
CustomFilterCacheSize: c.CustomFilterCacheSize,
|
||||||
SafeSearchCacheSize: c.SafeSearchCacheSize,
|
SafeSearchCacheSize: c.SafeSearchCacheSize,
|
||||||
// TODO(a.garipov): Consider making this configurable.
|
// TODO(a.garipov): Consider making this configurable.
|
||||||
SafeSearchCacheTTL: 1 * time.Hour,
|
SafeSearchCacheTTL: 1 * time.Hour,
|
||||||
RuleListCacheSize: c.RuleListCache.Size,
|
RuleListCacheSize: c.RuleListCache.Size,
|
||||||
RefreshIvl: c.RefreshIvl.Duration,
|
RefreshIvl: c.RefreshIvl.Duration,
|
||||||
UseRuleListCache: c.RuleListCache.Enabled,
|
IndexRefreshTimeout: c.IndexRefreshTimeout.Duration,
|
||||||
MaxRuleListSize: c.MaxSize.Bytes(),
|
RuleListRefreshTimeout: c.RuleListRefreshTimeout.Duration,
|
||||||
|
UseRuleListCache: c.RuleListCache.Enabled,
|
||||||
|
MaxRuleListSize: c.MaxSize.Bytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +105,10 @@ func (c *filtersConfig) validate() (err error) {
|
|||||||
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
||||||
case c.RefreshTimeout.Duration <= 0:
|
case c.RefreshTimeout.Duration <= 0:
|
||||||
return newMustBePositiveError("refresh_timeout", c.RefreshTimeout)
|
return newMustBePositiveError("refresh_timeout", c.RefreshTimeout)
|
||||||
|
case c.IndexRefreshTimeout.Duration <= 0:
|
||||||
|
return newMustBePositiveError("index_refresh_timeout", c.IndexRefreshTimeout)
|
||||||
|
case c.RuleListRefreshTimeout.Duration <= 0:
|
||||||
|
return newMustBePositiveError("rule_list_refresh_timeout", c.RuleListRefreshTimeout)
|
||||||
case c.MaxSize <= 0:
|
case c.MaxSize <= 0:
|
||||||
return newMustBePositiveError("max_size", c.MaxSize)
|
return newMustBePositiveError("max_size", c.MaxSize)
|
||||||
default:
|
default:
|
||||||
@ -138,7 +150,6 @@ func (c *fltRuleListCache) validate() (err error) {
|
|||||||
func setupFilterStorage(
|
func setupFilterStorage(
|
||||||
conf *filter.DefaultStorageConfig,
|
conf *filter.DefaultStorageConfig,
|
||||||
sigHdlr *service.SignalHandler,
|
sigHdlr *service.SignalHandler,
|
||||||
errColl errcoll.Interface,
|
|
||||||
refreshTimeout time.Duration,
|
refreshTimeout time.Duration,
|
||||||
) (strg *filter.DefaultStorage, err error) {
|
) (strg *filter.DefaultStorage, err error) {
|
||||||
strg, err = filter.NewDefaultStorage(conf)
|
strg, err = filter.NewDefaultStorage(conf)
|
||||||
@ -150,13 +161,11 @@ func setupFilterStorage(
|
|||||||
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||||
return context.WithTimeout(context.Background(), refreshTimeout)
|
return context.WithTimeout(context.Background(), refreshTimeout)
|
||||||
},
|
},
|
||||||
Refresher: strg,
|
Refresher: strg,
|
||||||
ErrColl: errColl,
|
Name: "filters",
|
||||||
Name: "filters",
|
Interval: conf.RefreshIvl,
|
||||||
Interval: conf.RefreshIvl,
|
RefreshOnShutdown: false,
|
||||||
RefreshOnShutdown: false,
|
RandomizeStart: false,
|
||||||
RoutineLogsAreDebug: false,
|
|
||||||
RandomizeStart: false,
|
|
||||||
})
|
})
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
"github.com/AdguardTeam/AdGuardDNS/internal/filter"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filtering Groups Configuration
|
// Filtering Groups Configuration
|
||||||
@ -94,7 +94,7 @@ func (g *filteringGroup) validate() (err error) {
|
|||||||
return errors.Error("no parental")
|
return errors.Error("no parental")
|
||||||
}
|
}
|
||||||
|
|
||||||
fltIDs := stringutil.NewSet()
|
fltIDs := container.NewMapSet[string]()
|
||||||
for i, fltID := range g.RuleLists.IDs {
|
for i, fltID := range g.RuleLists.IDs {
|
||||||
if fltIDs.Has(fltID) {
|
if fltIDs.Has(fltID) {
|
||||||
return fmt.Errorf("rule_lists: at index %d: duplicate id %q", i, fltID)
|
return fmt.Errorf("rule_lists: at index %d: duplicate id %q", i, fltID)
|
||||||
@ -160,7 +160,7 @@ func (groups filteringGroups) validate() (err error) {
|
|||||||
return errors.Error("no filtering_groups")
|
return errors.Error("no filtering_groups")
|
||||||
}
|
}
|
||||||
|
|
||||||
ids := stringutil.NewSet()
|
ids := container.NewMapSet[string]()
|
||||||
for i, g := range groups {
|
for i, g := range groups {
|
||||||
err = g.validate()
|
err = g.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
"github.com/AdguardTeam/AdGuardDNS/internal/geoip"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,14 +64,19 @@ func setupGeoIP(
|
|||||||
}
|
}
|
||||||
|
|
||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: ctxWithDefaultTimeout,
|
Context: ctxWithDefaultTimeout,
|
||||||
Refresher: geoIP,
|
// Do not add errColl to geoip's config, as that would create an import
|
||||||
ErrColl: errColl,
|
// cycle.
|
||||||
Name: "geoip",
|
Refresher: agdservice.NewRefresherWithErrColl(
|
||||||
Interval: conf.RefreshIvl.Duration,
|
geoIP,
|
||||||
RefreshOnShutdown: false,
|
log.Info,
|
||||||
RoutineLogsAreDebug: false,
|
errColl,
|
||||||
RandomizeStart: false,
|
"geoip_refresh",
|
||||||
|
),
|
||||||
|
Name: "geoip",
|
||||||
|
Interval: conf.RefreshIvl.Duration,
|
||||||
|
RefreshOnShutdown: false,
|
||||||
|
RandomizeStart: false,
|
||||||
})
|
})
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -35,7 +35,7 @@ func (c *interfaceListenersConfig) toInternal(
|
|||||||
ChannelBufferSize: c.ChannelBufferSize,
|
ChannelBufferSize: c.ChannelBufferSize,
|
||||||
})
|
})
|
||||||
|
|
||||||
err = mapsutil.OrderedRangeError(
|
err = mapsutil.SortedRangeError(
|
||||||
c.List,
|
c.List,
|
||||||
func(id bindtodevice.ID, l *interfaceListener) (addErr error) {
|
func(id bindtodevice.ID, l *interfaceListener) (addErr error) {
|
||||||
return errors.Annotate(m.Add(id, l.Interface, l.Port, ctrlConf), "adding listener %q: %w", id)
|
return errors.Annotate(m.Add(id, l.Interface, l.Port, ctrlConf), "adding listener %q: %w", id)
|
||||||
@ -66,7 +66,7 @@ func (c *interfaceListenersConfig) validate() (err error) {
|
|||||||
// Go on.
|
// Go on.
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mapsutil.OrderedRangeError(
|
err = mapsutil.SortedRangeError(
|
||||||
c.List,
|
c.List,
|
||||||
func(id bindtodevice.ID, l *interfaceListener) (lsnrErr error) {
|
func(id bindtodevice.ID, l *interfaceListener) (lsnrErr error) {
|
||||||
return errors.Annotate(l.validate(), "interface %q: %w", id)
|
return errors.Annotate(l.validate(), "interface %q: %w", id)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -88,7 +89,7 @@ func (o *rateLimitOptions) validate() (err error) {
|
|||||||
return errNilConfig
|
return errNilConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
return coalesceError(
|
return cmp.Or(
|
||||||
validatePositive("rps", o.RPS),
|
validatePositive("rps", o.RPS),
|
||||||
validatePositive("subnet_key_len", o.SubnetKeyLen),
|
validatePositive("subnet_key_len", o.SubnetKeyLen),
|
||||||
)
|
)
|
||||||
@ -120,7 +121,7 @@ func (c *rateLimitConfig) validate() (err error) {
|
|||||||
return fmt.Errorf("allowlist: %w", errNilConfig)
|
return fmt.Errorf("allowlist: %w", errNilConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
return coalesceError(
|
return cmp.Or(
|
||||||
validateProp("connection_limit", c.ConnectionLimit.validate),
|
validateProp("connection_limit", c.ConnectionLimit.validate),
|
||||||
validateProp("ipv4", c.IPv4.validate),
|
validateProp("ipv4", c.IPv4.validate),
|
||||||
validateProp("ipv6", c.IPv6.validate),
|
validateProp("ipv6", c.IPv6.validate),
|
||||||
@ -144,20 +145,18 @@ func setupRateLimiter(
|
|||||||
) (rateLimiter *ratelimit.Backoff, connLimiter *connlimiter.Limiter, err error) {
|
) (rateLimiter *ratelimit.Backoff, connLimiter *connlimiter.Limiter, err error) {
|
||||||
allowSubnets := netutil.UnembedPrefixes(conf.Allowlist.List)
|
allowSubnets := netutil.UnembedPrefixes(conf.Allowlist.List)
|
||||||
allowlist := ratelimit.NewDynamicAllowlist(allowSubnets, nil)
|
allowlist := ratelimit.NewDynamicAllowlist(allowSubnets, nil)
|
||||||
refresher, err := consul.NewAllowlistRefresher(allowlist, consulAllowlist)
|
refresher, err := consul.NewAllowlistRefresher(allowlist, consulAllowlist, errColl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("creating allowlist refresher: %w", err)
|
return nil, nil, fmt.Errorf("creating allowlist refresher: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: ctxWithDefaultTimeout,
|
Context: ctxWithDefaultTimeout,
|
||||||
Refresher: refresher,
|
Refresher: refresher,
|
||||||
ErrColl: errColl,
|
Name: "allowlist",
|
||||||
Name: "allowlist",
|
Interval: conf.Allowlist.RefreshIvl.Duration,
|
||||||
Interval: conf.Allowlist.RefreshIvl.Duration,
|
RefreshOnShutdown: false,
|
||||||
RefreshOnShutdown: false,
|
RandomizeStart: false,
|
||||||
RoutineLogsAreDebug: false,
|
|
||||||
RandomizeStart: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdnet"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
@ -37,13 +36,15 @@ type safeBrowsingConfig struct {
|
|||||||
|
|
||||||
// RefreshIvl defines how often AdGuard DNS refreshes the filter.
|
// RefreshIvl defines how often AdGuard DNS refreshes the filter.
|
||||||
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
RefreshIvl timeutil.Duration `yaml:"refresh_interval"`
|
||||||
|
|
||||||
|
// RefreshTimeout is the timeout for the filter update operation.
|
||||||
|
RefreshTimeout timeutil.Duration `yaml:"refresh_timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// toInternal converts c to the safe browsing filter configuration for the
|
// toInternal converts c to the safe browsing filter configuration for the
|
||||||
// filter storage of the DNS server. c is assumed to be valid.
|
// filter storage of the DNS server. c is assumed to be valid.
|
||||||
func (c *safeBrowsingConfig) toInternal(
|
func (c *safeBrowsingConfig) toInternal(
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
resolver agdnet.Resolver,
|
|
||||||
cloner *dnsmsg.Cloner,
|
cloner *dnsmsg.Cloner,
|
||||||
id agd.FilterListID,
|
id agd.FilterListID,
|
||||||
url *urlutil.URL,
|
url *urlutil.URL,
|
||||||
@ -60,11 +61,11 @@ func (c *safeBrowsingConfig) toInternal(
|
|||||||
Hashes: hashes,
|
Hashes: hashes,
|
||||||
URL: netutil.CloneURL(&url.URL),
|
URL: netutil.CloneURL(&url.URL),
|
||||||
ErrColl: errColl,
|
ErrColl: errColl,
|
||||||
Resolver: resolver,
|
|
||||||
ID: id,
|
ID: id,
|
||||||
CachePath: filepath.Join(cacheDir, string(id)),
|
CachePath: filepath.Join(cacheDir, string(id)),
|
||||||
ReplacementHost: c.BlockHost,
|
ReplacementHost: c.BlockHost,
|
||||||
Staleness: c.RefreshIvl.Duration,
|
Staleness: c.RefreshIvl.Duration,
|
||||||
|
RefreshTimeout: c.RefreshTimeout.Duration,
|
||||||
CacheTTL: c.CacheTTL.Duration,
|
CacheTTL: c.CacheTTL.Duration,
|
||||||
CacheSize: c.CacheSize,
|
CacheSize: c.CacheSize,
|
||||||
MaxSize: maxSize,
|
MaxSize: maxSize,
|
||||||
@ -85,6 +86,8 @@ func (c *safeBrowsingConfig) validate() (err error) {
|
|||||||
return newMustBePositiveError("cache_ttl", c.CacheTTL)
|
return newMustBePositiveError("cache_ttl", c.CacheTTL)
|
||||||
case c.RefreshIvl.Duration <= 0:
|
case c.RefreshIvl.Duration <= 0:
|
||||||
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
return newMustBePositiveError("refresh_interval", c.RefreshIvl)
|
||||||
|
case c.RefreshTimeout.Duration <= 0:
|
||||||
|
return newMustBePositiveError("refresh_timeout", c.RefreshTimeout)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -94,7 +97,6 @@ func (c *safeBrowsingConfig) validate() (err error) {
|
|||||||
// starts and registers its refresher in the signal handler.
|
// starts and registers its refresher in the signal handler.
|
||||||
func setupHashPrefixFilter(
|
func setupHashPrefixFilter(
|
||||||
conf *safeBrowsingConfig,
|
conf *safeBrowsingConfig,
|
||||||
resolver *agdnet.CachingResolver,
|
|
||||||
cloner *dnsmsg.Cloner,
|
cloner *dnsmsg.Cloner,
|
||||||
id agd.FilterListID,
|
id agd.FilterListID,
|
||||||
url *urlutil.URL,
|
url *urlutil.URL,
|
||||||
@ -103,7 +105,7 @@ func setupHashPrefixFilter(
|
|||||||
sigHdlr *service.SignalHandler,
|
sigHdlr *service.SignalHandler,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
) (strg *hashprefix.Storage, flt *hashprefix.Filter, err error) {
|
) (strg *hashprefix.Storage, flt *hashprefix.Filter, err error) {
|
||||||
fltConf, err := conf.toInternal(errColl, resolver, cloner, id, url, cachePath, maxSize)
|
fltConf, err := conf.toInternal(errColl, cloner, id, url, cachePath, maxSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("configuring hash prefix filter %s: %w", id, err)
|
return nil, nil, fmt.Errorf("configuring hash prefix filter %s: %w", id, err)
|
||||||
}
|
}
|
||||||
@ -114,14 +116,16 @@ func setupHashPrefixFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: ctxWithDefaultTimeout,
|
// Note that we also set the same timeout for the http.Client in
|
||||||
Refresher: flt,
|
// [hashprefix.NewFilter].
|
||||||
ErrColl: errColl,
|
Context: func() (ctx context.Context, cancel context.CancelFunc) {
|
||||||
Name: string(id),
|
return context.WithTimeout(context.Background(), fltConf.RefreshTimeout)
|
||||||
Interval: fltConf.Staleness,
|
},
|
||||||
RefreshOnShutdown: false,
|
Refresher: flt,
|
||||||
RoutineLogsAreDebug: false,
|
Name: string(id),
|
||||||
RandomizeStart: false,
|
Interval: fltConf.Staleness,
|
||||||
|
RefreshOnShutdown: false,
|
||||||
|
RandomizeStart: false,
|
||||||
})
|
})
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// toInternal returns the configuration of DNS servers for a single server
|
// toInternal returns the configuration of DNS servers for a single server
|
||||||
@ -95,7 +95,7 @@ func (srvs servers) validate() (needsTLS bool, err error) {
|
|||||||
return false, errors.Error("no servers")
|
return false, errors.Error("no servers")
|
||||||
}
|
}
|
||||||
|
|
||||||
names := stringutil.NewSet()
|
names := container.NewMapSet[string]()
|
||||||
for i, s := range srvs {
|
for i, s := range srvs {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return false, fmt.Errorf("at index %d: no server", i)
|
return false, fmt.Errorf("at index %d: no server", i)
|
||||||
@ -323,19 +323,17 @@ func (c *serverBindInterface) validate() (err error) {
|
|||||||
// Go on.
|
// Go on.
|
||||||
}
|
}
|
||||||
|
|
||||||
set := map[netip.Prefix]struct{}{}
|
set := container.NewMapSet[netip.Prefix]()
|
||||||
|
|
||||||
for i, subnet := range c.Subnets {
|
for i, subnet := range c.Subnets {
|
||||||
if !subnet.IsValid() {
|
if !subnet.IsValid() {
|
||||||
return fmt.Errorf("bad subnet at index %d", i)
|
return fmt.Errorf("bad subnet at index %d", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := set[subnet]
|
if set.Has(subnet) {
|
||||||
if ok {
|
|
||||||
return fmt.Errorf("duplicate subnet %s at index %d", subnet, i)
|
return fmt.Errorf("duplicate subnet %s at index %d", subnet, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
set[subnet] = struct{}{}
|
set.Add(subnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -2,14 +2,12 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/netutil"
|
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// serverGroups are the DNS server groups. A valid instance of serverGroups has
|
// serverGroups are the DNS server groups. A valid instance of serverGroups has
|
||||||
@ -41,11 +39,10 @@ func (srvGrps serverGroups) toInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
svcSrvGrps[i] = &agd.ServerGroup{
|
svcSrvGrps[i] = &agd.ServerGroup{
|
||||||
BlockPageRedirect: g.BlockPageRedirect.toInternal(),
|
DDR: g.DDR.toInternal(messages),
|
||||||
DDR: g.DDR.toInternal(messages),
|
TLS: tlsConf,
|
||||||
TLS: tlsConf,
|
Name: agd.ServerGroupName(g.Name),
|
||||||
Name: agd.ServerGroupName(g.Name),
|
FilteringGroup: fltGrpID,
|
||||||
FilteringGroup: fltGrpID,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
svcSrvGrps[i].Servers, err = g.Servers.toInternal(tlsConf, btdMgr, ratelimitConf, dnsConf)
|
svcSrvGrps[i].Servers, err = g.Servers.toInternal(tlsConf, btdMgr, ratelimitConf, dnsConf)
|
||||||
@ -63,7 +60,7 @@ func (srvGrps serverGroups) validate() (err error) {
|
|||||||
return errors.Error("no server groups")
|
return errors.Error("no server groups")
|
||||||
}
|
}
|
||||||
|
|
||||||
names := stringutil.NewSet()
|
names := container.NewMapSet[string]()
|
||||||
for i, g := range srvGrps {
|
for i, g := range srvGrps {
|
||||||
err = g.validate()
|
err = g.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -86,9 +83,6 @@ func (srvGrps serverGroups) validate() (err error) {
|
|||||||
// TODO(a.garipov): Think about more consistent naming, since this object is a
|
// TODO(a.garipov): Think about more consistent naming, since this object is a
|
||||||
// configuration, but it also stores other configurations.
|
// configuration, but it also stores other configurations.
|
||||||
type serverGroup struct {
|
type serverGroup struct {
|
||||||
// BlockPageRedirect is the configuration for the server group's block page.
|
|
||||||
BlockPageRedirect *serverGroupBlockPageConfig `yaml:"block_page_redirect"`
|
|
||||||
|
|
||||||
// DDR is the Discovery Of Designated Resolvers (DDR) configuration for this
|
// DDR is the Discovery Of Designated Resolvers (DDR) configuration for this
|
||||||
// server group.
|
// server group.
|
||||||
DDR *ddrConfig `yaml:"ddr"`
|
DDR *ddrConfig `yaml:"ddr"`
|
||||||
@ -117,11 +111,6 @@ func (g *serverGroup) validate() (err error) {
|
|||||||
return errors.Error("no filtering_group")
|
return errors.Error("no filtering_group")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = g.BlockPageRedirect.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("block_page_redirect: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = g.DDR.validate()
|
err = g.DDR.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ddr: %w", err)
|
return fmt.Errorf("ddr: %w", err)
|
||||||
@ -139,255 +128,3 @@ func (g *serverGroup) validate() (err error) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverGroupBlockPageConfig is the configuration for a [serverGroup]'s block
|
|
||||||
// page. See [agd.BlockPageRedirect] and the related types for more
|
|
||||||
// documentation and contracts.
|
|
||||||
type serverGroupBlockPageConfig struct {
|
|
||||||
// Apply defines request parameters based on which the block page is always
|
|
||||||
// shown.
|
|
||||||
Apply *serverGroupBlockPageApplyConfig `yaml:"apply"`
|
|
||||||
|
|
||||||
// Skip defines request parameters based on which the block page is never
|
|
||||||
// shown, regardless of the probability.
|
|
||||||
Skip *serverGroupBlockPageSkipConfig `yaml:"skip"`
|
|
||||||
|
|
||||||
// IPv4 are the IPv4 records of the block page, used to respond to A
|
|
||||||
// queries.
|
|
||||||
IPv4 []*serverGroupBlockPageRecord `yaml:"ipv4"`
|
|
||||||
|
|
||||||
// IPv6 are the IPv6 records of the block page, used to respond to AAAA
|
|
||||||
// queries.
|
|
||||||
IPv6 []*serverGroupBlockPageRecord `yaml:"ipv6"`
|
|
||||||
|
|
||||||
// Probability defines the probability of responding with the block page IPs
|
|
||||||
// based on remote address.
|
|
||||||
Probability float64 `yaml:"probability"`
|
|
||||||
|
|
||||||
// Enabled defines whether the block-page feature is enabled.
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// toInternal returns the block-page redirect configuration for a server group.
|
|
||||||
// c is assumed to be valid.
|
|
||||||
func (c *serverGroupBlockPageConfig) toInternal() (conf *agd.BlockPageRedirect) {
|
|
||||||
if !c.Enabled {
|
|
||||||
return &agd.BlockPageRedirect{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipv4 []netip.Addr
|
|
||||||
for _, r := range c.IPv4 {
|
|
||||||
ipv4 = append(ipv4, r.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipv6 []netip.Addr
|
|
||||||
for _, r := range c.IPv6 {
|
|
||||||
ipv6 = append(ipv6, r.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &agd.BlockPageRedirect{
|
|
||||||
Apply: c.Apply.toInternal(),
|
|
||||||
Skip: c.Skip.toInternal(),
|
|
||||||
IPv4: ipv4,
|
|
||||||
IPv6: ipv6,
|
|
||||||
Probability: agd.MustNewProbability(c.Probability),
|
|
||||||
Enabled: c.Enabled,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate returns an error if the block-page redirect configuration is
|
|
||||||
// invalid.
|
|
||||||
func (c *serverGroupBlockPageConfig) validate() (err error) {
|
|
||||||
switch {
|
|
||||||
case c == nil:
|
|
||||||
return errNilConfig
|
|
||||||
case !c.Enabled:
|
|
||||||
return nil
|
|
||||||
case len(c.IPv4) == 0 && len(c.IPv6) == 0:
|
|
||||||
return errors.Error("ipv4, ipv6, or both must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = agd.NewProbability(c.Probability)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("probability: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.validateAddrs()
|
|
||||||
if err != nil {
|
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.Apply.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("apply: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.Skip.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("skip: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// validateAddrs returns an error if the block-page redirect if the IP addresses
|
|
||||||
// in the block-page redirect configuration are invalid.
|
|
||||||
func (c *serverGroupBlockPageConfig) validateAddrs() (err error) {
|
|
||||||
for i, r := range c.IPv4 {
|
|
||||||
err = r.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ipv4: at index %d: address: %w", i, err)
|
|
||||||
} else if !r.Address.Is4() {
|
|
||||||
return fmt.Errorf("ipv4: at index %d: address: not ipv4: %v", i, r.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, r := range c.IPv6 {
|
|
||||||
err = r.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("ipv6: at index %d: %w", i, err)
|
|
||||||
} else if !r.Address.Is6() {
|
|
||||||
return fmt.Errorf("ipv6: at index %d: address: not ipv6: %v", i, r.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverGroupBlockPageRecord is a structure for defining answer records in
|
|
||||||
// [serverGroupBlockPageConfig].
|
|
||||||
type serverGroupBlockPageRecord struct {
|
|
||||||
Address netip.Addr `yaml:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate returns an error if the record configuration is invalid.
|
|
||||||
func (c *serverGroupBlockPageRecord) validate() (err error) {
|
|
||||||
switch {
|
|
||||||
case c == nil:
|
|
||||||
return errNilConfig
|
|
||||||
case !c.Address.IsValid():
|
|
||||||
return errors.Error("invalid addr")
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverGroupBlockPageApplyConfig defines the conditions for applying the
|
|
||||||
// block-page logic for a particular request.
|
|
||||||
type serverGroupBlockPageApplyConfig struct {
|
|
||||||
// Client are the parameters for clients for which block page is always
|
|
||||||
// enabled.
|
|
||||||
Client []*serverGroupBlockPageClientConfig `yaml:"client"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// toInternal returns the block-page redirect applying configuration for a
|
|
||||||
// server group. c is assumed to be valid.
|
|
||||||
func (c *serverGroupBlockPageApplyConfig) toInternal() (conf *agd.BlockPageRedirectApply) {
|
|
||||||
var subnets []netip.Prefix
|
|
||||||
for _, cli := range c.Client {
|
|
||||||
subnets = append(subnets, cli.Address.Prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &agd.BlockPageRedirectApply{
|
|
||||||
ClientSubnets: subnets,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate returns an error if the block-page redirect applying configuration
|
|
||||||
// is invalid.
|
|
||||||
func (c *serverGroupBlockPageApplyConfig) validate() (err error) {
|
|
||||||
if c == nil {
|
|
||||||
return errNilConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, cli := range c.Client {
|
|
||||||
err = cli.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("client: at index %d: %w", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverGroupBlockPageClientConfig is a common structure for defining clients
|
|
||||||
// in [serverGroupBlockPageSkipConfig] and [serverGroupBlockPageApplyConfig].
|
|
||||||
type serverGroupBlockPageClientConfig struct {
|
|
||||||
Address netutil.Prefix `yaml:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate returns an error if the client configuration is invalid.
|
|
||||||
func (c *serverGroupBlockPageClientConfig) validate() (err error) {
|
|
||||||
switch {
|
|
||||||
case c == nil:
|
|
||||||
return errNilConfig
|
|
||||||
case !c.Address.IsValid():
|
|
||||||
return errors.Error("invalid addr")
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverGroupBlockPageSkipConfig defines the conditions for skipping the block
|
|
||||||
// page logic for a particular request.
|
|
||||||
type serverGroupBlockPageSkipConfig struct {
|
|
||||||
// Client are the parameters for clients for which block page is always
|
|
||||||
// disabled.
|
|
||||||
Client []*serverGroupBlockPageClientConfig `yaml:"client"`
|
|
||||||
|
|
||||||
// QuestionDomains are the parameters for request questions for which block
|
|
||||||
// page is always disabled.
|
|
||||||
Question []*serverGroupBlockPageQuestionConfig `yaml:"question"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// toInternal returns the block-page redirect skipping configuration for a
|
|
||||||
// server group. c is assumed to be valid.
|
|
||||||
func (c *serverGroupBlockPageSkipConfig) toInternal() (conf *agd.BlockPageRedirectSkip) {
|
|
||||||
var subnets []netip.Prefix
|
|
||||||
for _, cli := range c.Client {
|
|
||||||
subnets = append(subnets, cli.Address.Prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
var domains []string
|
|
||||||
for _, q := range c.Question {
|
|
||||||
domains = append(domains, q.Domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &agd.BlockPageRedirectSkip{
|
|
||||||
ClientSubnets: subnets,
|
|
||||||
QuestionDomains: domains,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate returns an error if the block-page redirect skipping configuration
|
|
||||||
// is invalid.
|
|
||||||
func (c *serverGroupBlockPageSkipConfig) validate() (err error) {
|
|
||||||
if c == nil {
|
|
||||||
return errNilConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, cli := range c.Client {
|
|
||||||
err = cli.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("client: at index %d: %w", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, q := range c.Question {
|
|
||||||
switch {
|
|
||||||
case q == nil:
|
|
||||||
return fmt.Errorf("question: at index %d: %w", i, errNilConfig)
|
|
||||||
case q.Domain == "":
|
|
||||||
return fmt.Errorf("question: at index %d: %w", i, errors.Error("empty domain"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverGroupBlockPageQuestionConfig is a structure for defining question
|
|
||||||
// domains in [serverGroupBlockPageRedirectSkip].
|
|
||||||
type serverGroupBlockPageQuestionConfig struct {
|
|
||||||
Domain string `yaml:"domain"`
|
|
||||||
}
|
|
||||||
|
@ -15,9 +15,10 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/service"
|
"github.com/AdguardTeam/golibs/service"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ func (c *tlsConfig) validate(needsTLS bool) (err error) {
|
|||||||
// validateDeviceIDWildcards returns an error if the device ID domain wildcards
|
// validateDeviceIDWildcards returns an error if the device ID domain wildcards
|
||||||
// are invalid.
|
// are invalid.
|
||||||
func validateDeviceIDWildcards(wildcards []string) (err error) {
|
func validateDeviceIDWildcards(wildcards []string) (err error) {
|
||||||
s := stringutil.NewSet()
|
s := container.NewMapSet[string]()
|
||||||
for i, w := range wildcards {
|
for i, w := range wildcards {
|
||||||
// TODO(e.burkov): Consider removing this requirement.
|
// TODO(e.burkov): Consider removing this requirement.
|
||||||
if !strings.HasPrefix(w, "*.") {
|
if !strings.HasPrefix(w, "*.") {
|
||||||
@ -185,14 +186,18 @@ func (certs tlsConfigCerts) validate() (err error) {
|
|||||||
|
|
||||||
// ticketRotator is a refresh worker that rereads and resets TLS session tickets.
|
// ticketRotator is a refresh worker that rereads and resets TLS session tickets.
|
||||||
type ticketRotator struct {
|
type ticketRotator struct {
|
||||||
confs map[*tls.Config][]string
|
errColl errcoll.Interface
|
||||||
|
confs map[*tls.Config][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTicketRotator creates a new TLS session ticket rotator that rotates
|
// newTicketRotator creates a new TLS session ticket rotator that rotates
|
||||||
// tickets for the TLS configurations of all servers in grps.
|
// tickets for the TLS configurations of all servers in grps.
|
||||||
//
|
//
|
||||||
// grps is assumed to be valid.
|
// grps is assumed to be valid.
|
||||||
func newTicketRotator(grps []*agd.ServerGroup) (tr *ticketRotator, err error) {
|
func newTicketRotator(
|
||||||
|
errColl errcoll.Interface,
|
||||||
|
grps []*agd.ServerGroup,
|
||||||
|
) (tr *ticketRotator, err error) {
|
||||||
confs := map[*tls.Config][]string{}
|
confs := map[*tls.Config][]string{}
|
||||||
|
|
||||||
for _, g := range grps {
|
for _, g := range grps {
|
||||||
@ -209,7 +214,8 @@ func newTicketRotator(grps []*agd.ServerGroup) (tr *ticketRotator, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tr = &ticketRotator{
|
tr = &ticketRotator{
|
||||||
confs: confs,
|
errColl: errColl,
|
||||||
|
confs: confs,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tr.Refresh(context.Background())
|
err = tr.Refresh(context.Background())
|
||||||
@ -231,7 +237,17 @@ const sessTickLen = 32
|
|||||||
var _ agdservice.Refresher = (*ticketRotator)(nil)
|
var _ agdservice.Refresher = (*ticketRotator)(nil)
|
||||||
|
|
||||||
// Refresh implements the [agdservice.Refresher] interface for *ticketRotator.
|
// Refresh implements the [agdservice.Refresher] interface for *ticketRotator.
|
||||||
func (r *ticketRotator) Refresh(_ context.Context) (err error) {
|
func (r *ticketRotator) Refresh(ctx context.Context) (err error) {
|
||||||
|
// TODO(a.garipov): Use slog.
|
||||||
|
log.Debug("tickrot_refresh: started")
|
||||||
|
defer log.Debug("tickrot_refresh: finished")
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
errcoll.Collectf(ctx, r.errColl, "tickrot_refresh: %w", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for conf, files := range r.confs {
|
for conf, files := range r.confs {
|
||||||
keys := make([][sessTickLen]byte, 0, len(files))
|
keys := make([][sessTickLen]byte, 0, len(files))
|
||||||
|
|
||||||
@ -304,7 +320,7 @@ func setupTicketRotator(
|
|||||||
sigHdlr *service.SignalHandler,
|
sigHdlr *service.SignalHandler,
|
||||||
errColl errcoll.Interface,
|
errColl errcoll.Interface,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
tickRot, err := newTicketRotator(srvGrps)
|
tickRot, err := newTicketRotator(errColl, srvGrps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("setting up ticket rotator: %w", err)
|
return fmt.Errorf("setting up ticket rotator: %w", err)
|
||||||
}
|
}
|
||||||
@ -312,13 +328,11 @@ func setupTicketRotator(
|
|||||||
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
refr := agdservice.NewRefreshWorker(&agdservice.RefreshWorkerConfig{
|
||||||
Context: ctxWithDefaultTimeout,
|
Context: ctxWithDefaultTimeout,
|
||||||
Refresher: tickRot,
|
Refresher: tickRot,
|
||||||
ErrColl: errColl,
|
|
||||||
Name: "tickrot",
|
Name: "tickrot",
|
||||||
// TODO(ameshkov): Consider making configurable.
|
// TODO(ameshkov): Consider making configurable.
|
||||||
Interval: 1 * time.Minute,
|
Interval: 1 * time.Minute,
|
||||||
RefreshOnShutdown: false,
|
RefreshOnShutdown: false,
|
||||||
RoutineLogsAreDebug: true,
|
RandomizeStart: false,
|
||||||
RandomizeStart: false,
|
|
||||||
})
|
})
|
||||||
err = refr.Start(context.Background())
|
err = refr.Start(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/prometheus"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/prometheus"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/service"
|
"github.com/AdguardTeam/golibs/service"
|
||||||
"github.com/AdguardTeam/golibs/timeutil"
|
"github.com/AdguardTeam/golibs/timeutil"
|
||||||
)
|
)
|
||||||
@ -73,7 +75,7 @@ func (c *upstreamConfig) validate() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return coalesceError(
|
return cmp.Or(
|
||||||
validateProp("fallback", c.Fallback.validate),
|
validateProp("fallback", c.Fallback.validate),
|
||||||
validateProp("healthcheck", c.Healthcheck.validate),
|
validateProp("healthcheck", c.Healthcheck.validate),
|
||||||
)
|
)
|
||||||
@ -171,13 +173,16 @@ func newUpstreamHealthcheck(
|
|||||||
conf.Healthcheck.Timeout.Duration,
|
conf.Healthcheck.Timeout.Duration,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
Refresher: handler,
|
Refresher: agdservice.NewRefresherWithErrColl(
|
||||||
ErrColl: errColl,
|
handler,
|
||||||
Name: "upstream healthcheck",
|
log.Debug,
|
||||||
Interval: conf.Healthcheck.Interval.Duration,
|
errColl,
|
||||||
RefreshOnShutdown: false,
|
"upstream_healthcheck_refresh",
|
||||||
RoutineLogsAreDebug: true,
|
),
|
||||||
RandomizeStart: false,
|
Name: "upstream healthcheck",
|
||||||
|
Interval: conf.Healthcheck.Interval.Duration,
|
||||||
|
RefreshOnShutdown: false,
|
||||||
|
RandomizeStart: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,15 @@ type webConfig struct {
|
|||||||
// LinkedIP is the optional linked IP web server.
|
// LinkedIP is the optional linked IP web server.
|
||||||
LinkedIP *linkedIPServer `yaml:"linked_ip"`
|
LinkedIP *linkedIPServer `yaml:"linked_ip"`
|
||||||
|
|
||||||
// SafeBrowsing is the optional safe browsing block page web server.
|
|
||||||
SafeBrowsing *blockPageServer `yaml:"safe_browsing"`
|
|
||||||
|
|
||||||
// AdultBlocking is the optional adult blocking block page web server.
|
// AdultBlocking is the optional adult blocking block page web server.
|
||||||
AdultBlocking *blockPageServer `yaml:"adult_blocking"`
|
AdultBlocking *blockPageServer `yaml:"adult_blocking"`
|
||||||
|
|
||||||
|
// GeneralBlocking is the optional general block-page web server.
|
||||||
|
GeneralBlocking *blockPageServer `yaml:"general_blocking"`
|
||||||
|
|
||||||
|
// SafeBrowsing is the optional safe browsing block page web server.
|
||||||
|
SafeBrowsing *blockPageServer `yaml:"safe_browsing"`
|
||||||
|
|
||||||
// RootRedirectURL is the URL to which non-DNS and non-Debug HTTP requests
|
// RootRedirectURL is the URL to which non-DNS and non-Debug HTTP requests
|
||||||
// are redirected. If not set, a 404 page is shown.
|
// are redirected. If not set, a 404 page is shown.
|
||||||
RootRedirectURL *urlutil.URL `yaml:"root_redirect_url"`
|
RootRedirectURL *urlutil.URL `yaml:"root_redirect_url"`
|
||||||
@ -86,6 +89,11 @@ func (c *webConfig) toInternal(
|
|||||||
return nil, fmt.Errorf("converting adult_blocking: %w", err)
|
return nil, fmt.Errorf("converting adult_blocking: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf.GeneralBlocking, err = c.GeneralBlocking.toInternal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("converting general_blocking: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
conf.SafeBrowsing, err = c.SafeBrowsing.toInternal()
|
conf.SafeBrowsing, err = c.SafeBrowsing.toInternal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("converting safe_browsing: %w", err)
|
return nil, fmt.Errorf("converting safe_browsing: %w", err)
|
||||||
@ -146,16 +154,21 @@ func (c *webConfig) validate() (err error) {
|
|||||||
return fmt.Errorf("linked_ip: %w", err)
|
return fmt.Errorf("linked_ip: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.SafeBrowsing.validate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("safe_browsing: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.AdultBlocking.validate()
|
err = c.AdultBlocking.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("adult_blocking: %w", err)
|
return fmt.Errorf("adult_blocking: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = c.GeneralBlocking.validate()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("general_blocking: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.SafeBrowsing.validate()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("safe_browsing: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = c.StaticContent.validate()
|
err = c.StaticContent.validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("static_content: %w", err)
|
return fmt.Errorf("static_content: %w", err)
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdservice"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/errcoll"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
@ -23,12 +24,14 @@ type AllowlistRefresher struct {
|
|||||||
allowlist *ratelimit.DynamicAllowlist
|
allowlist *ratelimit.DynamicAllowlist
|
||||||
http *agdhttp.Client
|
http *agdhttp.Client
|
||||||
url *url.URL
|
url *url.URL
|
||||||
|
errColl errcoll.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAllowlistRefresher returns a properly initialized *AllowlistRefresher.
|
// NewAllowlistRefresher returns a properly initialized *AllowlistRefresher.
|
||||||
func NewAllowlistRefresher(
|
func NewAllowlistRefresher(
|
||||||
allowlist *ratelimit.DynamicAllowlist,
|
allowlist *ratelimit.DynamicAllowlist,
|
||||||
consulURL *url.URL,
|
consulURL *url.URL,
|
||||||
|
errColl errcoll.Interface,
|
||||||
) (l *AllowlistRefresher, err error) {
|
) (l *AllowlistRefresher, err error) {
|
||||||
l = &AllowlistRefresher{
|
l = &AllowlistRefresher{
|
||||||
allowlist: allowlist,
|
allowlist: allowlist,
|
||||||
@ -36,7 +39,8 @@ func NewAllowlistRefresher(
|
|||||||
// TODO(a.garipov): Consider making configurable.
|
// TODO(a.garipov): Consider making configurable.
|
||||||
Timeout: 15 * time.Second,
|
Timeout: 15 * time.Second,
|
||||||
}),
|
}),
|
||||||
url: consulURL,
|
url: consulURL,
|
||||||
|
errColl: errColl,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l.Refresh(context.Background())
|
err = l.Refresh(context.Background())
|
||||||
@ -53,6 +57,10 @@ var _ agdservice.Refresher = (*AllowlistRefresher)(nil)
|
|||||||
// Refresh implements the [agdservice.Refresher] interface for
|
// Refresh implements the [agdservice.Refresher] interface for
|
||||||
// *AllowlistRefresher.
|
// *AllowlistRefresher.
|
||||||
func (l *AllowlistRefresher) Refresh(ctx context.Context) (err error) {
|
func (l *AllowlistRefresher) Refresh(ctx context.Context) (err error) {
|
||||||
|
// TODO(a.garipov): Use slog.
|
||||||
|
log.Info("allowlist_refresh: started")
|
||||||
|
defer log.Info("allowlist_refresh: finished")
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
metrics.ConsulAllowlistUpdateTime.SetToCurrentTime()
|
metrics.ConsulAllowlistUpdateTime.SetToCurrentTime()
|
||||||
metrics.SetStatusGauge(metrics.ConsulAllowlistUpdateStatus, err)
|
metrics.SetStatusGauge(metrics.ConsulAllowlistUpdateStatus, err)
|
||||||
@ -60,7 +68,10 @@ func (l *AllowlistRefresher) Refresh(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
consulNets, err := l.loadConsul(ctx)
|
consulNets, err := l.loadConsul(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading consul: %w", err)
|
errcoll.Collectf(ctx, l.errColl, "allowlist_refresh: %w", err)
|
||||||
|
|
||||||
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("allowlist: loaded %d records from %s", len(consulNets), l.url)
|
log.Info("allowlist: loaded %d records from %s", len(consulNets), l.url)
|
||||||
|
@ -2,6 +2,7 @@ package consul_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdhttp"
|
||||||
|
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
"github.com/AdguardTeam/AdGuardDNS/internal/consul"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/ratelimit"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
@ -70,12 +72,18 @@ func TestNewAllowlistRefresher(t *testing.T) {
|
|||||||
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
||||||
pt := testutil.PanicT{}
|
pt := testutil.PanicT{}
|
||||||
|
|
||||||
_, err := rw.Write([]byte(testCases[i].resp))
|
_, err := io.WriteString(rw, testCases[i].resp)
|
||||||
require.NoError(pt, err)
|
require.NoError(pt, err)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
_, err := consul.NewAllowlistRefresher(al, u)
|
errColl := &agdtest.ErrorCollector{
|
||||||
|
OnCollect: func(_ context.Context, err error) {
|
||||||
|
panic("not implemented")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, ip := range tc.wantAllow {
|
for _, ip := range tc.wantAllow {
|
||||||
@ -104,10 +112,18 @@ func TestNewAllowlistRefresher(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
wantErr := &agdhttp.StatusError{}
|
wantErr := &agdhttp.StatusError{}
|
||||||
|
|
||||||
_, err := consul.NewAllowlistRefresher(al, u)
|
var gotCollErr error
|
||||||
|
errColl := &agdtest.ErrorCollector{
|
||||||
|
OnCollect: func(_ context.Context, err error) {
|
||||||
|
gotCollErr = err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||||
require.ErrorAs(t, err, &wantErr)
|
require.ErrorAs(t, err, &wantErr)
|
||||||
|
|
||||||
assert.Equal(t, wantErr.Got, status)
|
assert.Equal(t, wantErr.Got, status)
|
||||||
|
assert.ErrorAs(t, gotCollErr, &wantErr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,11 +132,18 @@ func TestAllowlistRefresher_Refresh_deadline(t *testing.T) {
|
|||||||
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
u := handleWithURL(t, http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
|
||||||
pt := testutil.PanicT{}
|
pt := testutil.PanicT{}
|
||||||
|
|
||||||
_, err := rw.Write([]byte(`[]`))
|
_, err := io.WriteString(rw, `[]`)
|
||||||
require.NoError(pt, err)
|
require.NoError(pt, err)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
c, err := consul.NewAllowlistRefresher(al, u)
|
var gotCollErr error
|
||||||
|
errColl := &agdtest.ErrorCollector{
|
||||||
|
OnCollect: func(_ context.Context, err error) {
|
||||||
|
gotCollErr = err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := consul.NewAllowlistRefresher(al, u, errColl)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@ -128,4 +151,5 @@ func TestAllowlistRefresher_Refresh_deadline(t *testing.T) {
|
|||||||
|
|
||||||
err = c.Refresh(ctx)
|
err = c.Refresh(ctx)
|
||||||
assert.ErrorIs(t, err, context.Canceled)
|
assert.ErrorIs(t, err, context.Canceled)
|
||||||
|
assert.ErrorIs(t, gotCollErr, context.Canceled)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
"github.com/AdguardTeam/AdGuardDNS/internal/debugsvc"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -45,11 +44,11 @@ func TestService_Start(t *testing.T) {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
require.NotPanics(t, func() {
|
require.NotPanics(t, func() {
|
||||||
err = svc.Start(agdtest.ContextWithTimeout(t, testTimeout))
|
err = svc.Start(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
||||||
return svc.Shutdown(agdtest.ContextWithTimeout(t, testTimeout))
|
return svc.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
})
|
})
|
||||||
|
|
||||||
client := http.Client{
|
client := http.Client{
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
"github.com/AdguardTeam/AdGuardDNS/internal/metrics"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ func (b *buffer) all() (records []*record) {
|
|||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
for key, val := range b.entries {
|
for key, val := range b.entries {
|
||||||
if len(val.answers) == 0 {
|
if val.answers.Len() == 0 {
|
||||||
records = append(records, &record{
|
records = append(records, &record{
|
||||||
target: key.target,
|
target: key.target,
|
||||||
hits: val.hits,
|
hits: val.hits,
|
||||||
@ -73,7 +74,7 @@ func (b *buffer) all() (records []*record) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for a := range val.answers {
|
val.answers.Range(func(a recordAnswer) (cont bool) {
|
||||||
records = append(records, &record{
|
records = append(records, &record{
|
||||||
target: key.target,
|
target: key.target,
|
||||||
answer: a.value,
|
answer: a.value,
|
||||||
@ -81,24 +82,26 @@ func (b *buffer) all() (records []*record) {
|
|||||||
rrType: a.rrType,
|
rrType: a.rrType,
|
||||||
rcode: a.rcode,
|
rcode: a.rcode,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
// toAnswerSet converts a slice of [dns.RR] to a map that can easier be
|
// toAnswerSet converts a slice of [dns.RR] to a set that can easier be
|
||||||
// serialized to a csv.
|
// serialized to a csv.
|
||||||
func toAnswerSet(answers []dns.RR, rc dnsmsg.RCode) (answerSet map[recordAnswer]unit) {
|
func toAnswerSet(answers []dns.RR, rc dnsmsg.RCode) (answerSet *container.MapSet[recordAnswer]) {
|
||||||
answerSet = map[recordAnswer]unit{}
|
answerSet = container.NewMapSet[recordAnswer]()
|
||||||
for _, a := range answers {
|
for _, a := range answers {
|
||||||
ansStr := answerString(a)
|
ansStr := answerString(a)
|
||||||
if ansStr != "" {
|
if ansStr != "" {
|
||||||
answerSet[recordAnswer{
|
answerSet.Add(recordAnswer{
|
||||||
value: ansStr,
|
value: ansStr,
|
||||||
rrType: a.Header().Rrtype,
|
rrType: a.Header().Rrtype,
|
||||||
rcode: rc,
|
rcode: rc,
|
||||||
}] = unit{}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,12 @@ func (db *Default) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var rw io.Writer = w
|
var rw io.Writer = w
|
||||||
// TODO(a.garipov): Consider parsing the quality value.
|
|
||||||
if strings.Contains(r.Header.Get(httphdr.AcceptEncoding), "gzip") {
|
// TODO(a.garipov): Parse the quality value.
|
||||||
h.Set(httphdr.ContentEncoding, "gzip")
|
//
|
||||||
|
// TODO(a.garipov): Support other compression algorithms.
|
||||||
|
if strings.Contains(r.Header.Get(httphdr.AcceptEncoding), agdhttp.HdrValGzip) {
|
||||||
|
h.Set(httphdr.ContentEncoding, agdhttp.HdrValGzip)
|
||||||
gw := gzip.NewWriter(w)
|
gw := gzip.NewWriter(w)
|
||||||
defer func() { err = errors.WithDeferred(err, gw.Close()) }()
|
defer func() { err = errors.WithDeferred(err, gw.Close()) }()
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ func TestDefault_ServeHTTP(t *testing.T) {
|
|||||||
successHdr := http.Header{
|
successHdr := http.Header{
|
||||||
httphdr.ContentType: []string{agdhttp.HdrValTextCSV},
|
httphdr.ContentType: []string{agdhttp.HdrValTextCSV},
|
||||||
httphdr.Trailer: []string{httphdr.XError},
|
httphdr.Trailer: []string{httphdr.XError},
|
||||||
httphdr.ContentEncoding: []string{"gzip"},
|
httphdr.ContentEncoding: []string{agdhttp.HdrValGzip},
|
||||||
}
|
}
|
||||||
|
|
||||||
newMsg := func(rcode int, name string, qtype uint16) (m *dns.Msg) {
|
newMsg := func(rcode int, name string, qtype uint16) (m *dns.Msg) {
|
||||||
@ -112,7 +112,7 @@ func TestDefault_ServeHTTP(t *testing.T) {
|
|||||||
(&url.URL{Scheme: "http", Host: "example.com"}).String(),
|
(&url.URL{Scheme: "http", Host: "example.com"}).String(),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
r.Header.Add(httphdr.AcceptEncoding, "gzip")
|
r.Header.Add(httphdr.AcceptEncoding, agdhttp.HdrValGzip)
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
db := dnsdb.New(&dnsdb.DefaultConfig{
|
db := dnsdb.New(&dnsdb.DefaultConfig{
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
|
||||||
|
"github.com/AdguardTeam/golibs/container"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,12 +70,9 @@ type recordKey struct {
|
|||||||
qt dnsmsg.RRType
|
qt dnsmsg.RRType
|
||||||
}
|
}
|
||||||
|
|
||||||
// unit is a convenient alias for struct{}.
|
|
||||||
type unit = struct{}
|
|
||||||
|
|
||||||
// recordValue contains the values for a single record key.
|
// recordValue contains the values for a single record key.
|
||||||
type recordValue struct {
|
type recordValue struct {
|
||||||
answers map[recordAnswer]unit
|
answers *container.MapSet[recordAnswer]
|
||||||
hits uint64
|
hits uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,15 @@ type BlockingMode interface {
|
|||||||
|
|
||||||
// BlockingModeCustomIP makes the [dnsmsg.Constructor] return responses with
|
// BlockingModeCustomIP makes the [dnsmsg.Constructor] return responses with
|
||||||
// custom IP addresses to A and AAAA requests. For all other types of requests,
|
// custom IP addresses to A and AAAA requests. For all other types of requests,
|
||||||
// as well as if one of the addresses isn't set, it returns a response with no
|
// as well as in case the address corresponding to IP version is not set, it
|
||||||
// answers (aka NODATA).
|
// returns a response with no answers (aka NODATA).
|
||||||
type BlockingModeCustomIP struct {
|
type BlockingModeCustomIP struct {
|
||||||
IPv4 netip.Addr
|
// IPv4 is a slice of valid IPv4 addresses used in responses to A requests.
|
||||||
IPv6 netip.Addr
|
IPv4 []netip.Addr
|
||||||
|
|
||||||
|
// IPv6 is a slice of valid IPv6 addresses used in responses to AAAA
|
||||||
|
// requests.
|
||||||
|
IPv6 []netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBlockingMode implements the BlockingMode interface for
|
// isBlockingMode implements the BlockingMode interface for
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
// Cloner is a pool that can clone common parts of DNS messages with fewer
|
// Cloner is a pool that can clone common parts of DNS messages with fewer
|
||||||
// allocations.
|
// allocations.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Use in filtering when cloning a [filter.ResultModified]
|
// TODO(a.garipov): Use in filtering when cloning a
|
||||||
// message.
|
// [filter.ResultModifiedResponse] message.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Use in [Constructor].
|
// TODO(a.garipov): Use in [Constructor].
|
||||||
type Cloner struct {
|
type Cloner struct {
|
||||||
|
@ -328,7 +328,7 @@ func BenchmarkClone(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
msgSink = dnsmsg.Clone(tc.msg)
|
msgSink = dnsmsg.Clone(tc.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ func BenchmarkCloner_Clone(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := range b.N {
|
||||||
msgSink = c.Clone(tc.msg)
|
msgSink = c.Clone(tc.msg)
|
||||||
if i < b.N-1 {
|
if i < b.N-1 {
|
||||||
// Don't dispose of the last one to be sure that we can
|
// Don't dispose of the last one to be sure that we can
|
||||||
|
@ -33,6 +33,17 @@ func NewConstructor(cloner *Cloner, bm BlockingMode, respTTL time.Duration) (c *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cloner returns the constructor's Cloner.
|
||||||
|
func (c *Constructor) Cloner() (cloner *Cloner) {
|
||||||
|
return c.cloner
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilteredResponseTTL returns the TTL that the constructor uses to build
|
||||||
|
// blocked responses.
|
||||||
|
func (c *Constructor) FilteredResponseTTL() (ttl time.Duration) {
|
||||||
|
return c.fltRespTTL
|
||||||
|
}
|
||||||
|
|
||||||
// NewBlockedRespMsg returns a blocked DNS response message based on the
|
// NewBlockedRespMsg returns a blocked DNS response message based on the
|
||||||
// constructor's blocking mode.
|
// constructor's blocking mode.
|
||||||
func (c *Constructor) NewBlockedRespMsg(req *dns.Msg) (msg *dns.Msg, err error) {
|
func (c *Constructor) NewBlockedRespMsg(req *dns.Msg) (msg *dns.Msg, err error) {
|
||||||
@ -65,12 +76,12 @@ func (c *Constructor) newBlockedCustomIPRespMsg(
|
|||||||
) (msg *dns.Msg, err error) {
|
) (msg *dns.Msg, err error) {
|
||||||
switch qt := req.Question[0].Qtype; qt {
|
switch qt := req.Question[0].Qtype; qt {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
if m.IPv4.IsValid() {
|
if len(m.IPv4) > 0 {
|
||||||
return c.NewIPRespMsg(req, m.IPv4)
|
return c.NewIPRespMsg(req, m.IPv4...)
|
||||||
}
|
}
|
||||||
case dns.TypeAAAA:
|
case dns.TypeAAAA:
|
||||||
if m.IPv6.IsValid() {
|
if len(m.IPv6) > 0 {
|
||||||
return c.NewIPRespMsg(req, m.IPv6)
|
return c.NewIPRespMsg(req, m.IPv6...)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Go on.
|
// Go on.
|
||||||
@ -202,7 +213,7 @@ func (c *Constructor) AppendDebugExtra(req, resp *dns.Msg, str string) (err erro
|
|||||||
|
|
||||||
// TODO(a.garipov): Use slices.Chunk in Go 1.23.
|
// TODO(a.garipov): Use slices.Chunk in Go 1.23.
|
||||||
newStr := make([]string, strNum)
|
newStr := make([]string, strNum)
|
||||||
for i := 0; i < strNum; i++ {
|
for i := range strNum {
|
||||||
start := i * MaxTXTStringLen
|
start := i * MaxTXTStringLen
|
||||||
|
|
||||||
var cutStr string
|
var cutStr string
|
||||||
|
@ -2,6 +2,7 @@ package dnsmsg_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -81,26 +82,34 @@ func TestConstructor_NewBlockedRespMsg_customIP(t *testing.T) {
|
|||||||
wantAAAA bool
|
wantAAAA bool
|
||||||
}{{
|
}{{
|
||||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||||
IPv4: testIPv4,
|
IPv4: []netip.Addr{testIPv4},
|
||||||
IPv6: testIPv6,
|
IPv6: []netip.Addr{testIPv6},
|
||||||
}, testFltRespTTL),
|
}, testFltRespTTL),
|
||||||
name: "both",
|
name: "both",
|
||||||
wantA: true,
|
wantA: true,
|
||||||
wantAAAA: true,
|
wantAAAA: true,
|
||||||
}, {
|
}, {
|
||||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||||
IPv4: testIPv4,
|
IPv4: []netip.Addr{testIPv4},
|
||||||
}, testFltRespTTL),
|
}, testFltRespTTL),
|
||||||
name: "ipv4_only",
|
name: "ipv4_only",
|
||||||
wantA: true,
|
wantA: true,
|
||||||
wantAAAA: false,
|
wantAAAA: false,
|
||||||
}, {
|
}, {
|
||||||
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||||
IPv6: testIPv6,
|
IPv6: []netip.Addr{testIPv6},
|
||||||
}, testFltRespTTL),
|
}, testFltRespTTL),
|
||||||
name: "ipv6_only",
|
name: "ipv6_only",
|
||||||
wantA: false,
|
wantA: false,
|
||||||
wantAAAA: true,
|
wantAAAA: true,
|
||||||
|
}, {
|
||||||
|
messages: dnsmsg.NewConstructor(nil, &dnsmsg.BlockingModeCustomIP{
|
||||||
|
IPv4: []netip.Addr{},
|
||||||
|
IPv6: []netip.Addr{},
|
||||||
|
}, testFltRespTTL),
|
||||||
|
name: "empty",
|
||||||
|
wantA: false,
|
||||||
|
wantAAAA: false,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
2
internal/dnsserver/cache/cache_test.go
vendored
2
internal/dnsserver/cache/cache_test.go
vendored
@ -194,7 +194,7 @@ func TestMiddleware_Wrap(t *testing.T) {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
var nrw *dnsserver.NonWriterResponseWriter
|
var nrw *dnsserver.NonWriterResponseWriter
|
||||||
for i := 0; i < N; i++ {
|
for range N {
|
||||||
addr := &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 53}
|
addr := &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 53}
|
||||||
nrw = dnsserver.NewNonWriterResponseWriter(addr, addr)
|
nrw = dnsserver.NewNonWriterResponseWriter(addr, addr)
|
||||||
err = withCache.ServeDNS(context.Background(), nrw, tc.req)
|
err = withCache.ServeDNS(context.Background(), nrw, tc.req)
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Handler is an interface that defines how the DNS server would process DNS
|
// Handler is an interface that defines how the DNS server would process DNS
|
||||||
// queries. Inspired by net/http.Server and it's Handler.
|
// queries. Inspired by net/http.Server and it's Handler.
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
// ServeDNS should process the request and write a DNS response to the
|
// ServeDNS should process the request and write a DNS response to the
|
||||||
// specified ResponseWriter.
|
// specified ResponseWriter.
|
||||||
@ -28,7 +28,7 @@ type Handler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
||||||
// as DNS handlers. If f is a function with the appropriate signature,
|
// as DNS handlers. If f is a function with the appropriate signature,
|
||||||
// HandlerFunc(f) is a Handler that calls f.
|
// HandlerFunc(f) is a Handler that calls f.
|
||||||
type HandlerFunc func(context.Context, ResponseWriter, *dns.Msg) (err error)
|
type HandlerFunc func(context.Context, ResponseWriter, *dns.Msg) (err error)
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package dnsserver_test
|
package dnsserver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||||
"github.com/AdguardTeam/golibs/testutil"
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
@ -15,16 +13,3 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
// testTimeout is a common timeout for tests.
|
// testTimeout is a common timeout for tests.
|
||||||
const testTimeout = dnsserver.DefaultReadTimeout
|
const testTimeout = dnsserver.DefaultReadTimeout
|
||||||
|
|
||||||
// contextWithTimeout is a helper that creates a new context with timeout and
|
|
||||||
// registers ctx's cleanup with t.Cleanup.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Move to golibs and DRY.
|
|
||||||
func contextWithTimeout(tb testing.TB, timeout time.Duration) (ctx context.Context) {
|
|
||||||
tb.Helper()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
||||||
tb.Cleanup(cancel)
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
@ -33,7 +33,7 @@ func CreateTestHandler(recordsCount int) (h dnsserver.Handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ip := netutil.IPv4Localhost().Prev()
|
ip := netutil.IPv4Localhost().Prev()
|
||||||
for i := 0; i < recordsCount; i++ {
|
for range recordsCount {
|
||||||
// Add 1 to make sure that each IP is valid.
|
// Add 1 to make sure that each IP is valid.
|
||||||
ip = ip.Next()
|
ip = ip.Next()
|
||||||
ans = append(ans, &dns.A{Hdr: hdr, A: ip.AsSlice()})
|
ans = append(ans, &dns.A{Hdr: hdr, A: ip.AsSlice()})
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"golang.org/x/exp/rand"
|
"golang.org/x/exp/rand"
|
||||||
)
|
)
|
||||||
@ -265,6 +266,10 @@ func (h *Handler) exchange(
|
|||||||
// upstreams is detected to be up again, requests are redirected back to the
|
// upstreams is detected to be up again, requests are redirected back to the
|
||||||
// main upstreams.
|
// main upstreams.
|
||||||
func (h *Handler) Refresh(ctx context.Context) (err error) {
|
func (h *Handler) Refresh(ctx context.Context) (err error) {
|
||||||
|
// TODO(a.garipov): Use slog.
|
||||||
|
log.Debug("upstream_healthcheck_refresh: started")
|
||||||
|
defer log.Debug("upstream_healthcheck_refresh: finished")
|
||||||
|
|
||||||
return h.refresh(ctx, false)
|
return h.refresh(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,18 +21,6 @@ func TestMain(m *testing.M) {
|
|||||||
// testTimeout is the timeout for tests.
|
// testTimeout is the timeout for tests.
|
||||||
const testTimeout = 1 * time.Second
|
const testTimeout = 1 * time.Second
|
||||||
|
|
||||||
// newTimeoutCtx is a test helper that returns a context with a timeout of
|
|
||||||
// [testTimeout] and its cancel function being called in the test cleanup. It
|
|
||||||
// should not be used where cancelation is expected sooner.
|
|
||||||
func newTimeoutCtx(tb testing.TB, parent context.Context) (ctx context.Context) {
|
|
||||||
tb.Helper()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(parent, testTimeout)
|
|
||||||
tb.Cleanup(cancel)
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandler_ServeDNS(t *testing.T) {
|
func TestHandler_ServeDNS(t *testing.T) {
|
||||||
srv, addr := dnsservertest.RunDNSServer(t, dnsservertest.DefaultHandler())
|
srv, addr := dnsservertest.RunDNSServer(t, dnsservertest.DefaultHandler())
|
||||||
|
|
||||||
@ -49,7 +37,7 @@ func TestHandler_ServeDNS(t *testing.T) {
|
|||||||
rw := dnsserver.NewNonWriterResponseWriter(srv.LocalUDPAddr(), srv.LocalUDPAddr())
|
rw := dnsserver.NewNonWriterResponseWriter(srv.LocalUDPAddr(), srv.LocalUDPAddr())
|
||||||
|
|
||||||
// Check the handler's ServeDNS method
|
// Check the handler's ServeDNS method
|
||||||
err := handler.ServeDNS(newTimeoutCtx(t, context.Background()), rw, req)
|
err := handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
res := rw.Msg()
|
res := rw.Msg()
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/dnsservertest"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/dnsservertest"
|
||||||
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/forward"
|
"github.com/AdguardTeam/AdGuardDNS/internal/dnsserver/forward"
|
||||||
|
"github.com/AdguardTeam/golibs/testutil"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -63,32 +64,30 @@ func TestHandler_Refresh(t *testing.T) {
|
|||||||
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
||||||
rw := dnsserver.NewNonWriterResponseWriter(fallback.LocalUDPAddr(), fallback.LocalUDPAddr())
|
rw := dnsserver.NewNonWriterResponseWriter(fallback.LocalUDPAddr(), fallback.LocalUDPAddr())
|
||||||
|
|
||||||
ctx := context.Background()
|
err := handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||||
|
|
||||||
err := handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, int64(2), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(2), upstreamRequestsCount.Load())
|
||||||
|
|
||||||
err = handler.Refresh(newTimeoutCtx(t, ctx))
|
err = handler.Refresh(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||||
|
|
||||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||||
|
|
||||||
// Now, set upstream up.
|
// Now, set upstream up.
|
||||||
upstreamIsUp.Store(true)
|
upstreamIsUp.Store(true)
|
||||||
|
|
||||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(4), upstreamRequestsCount.Load())
|
||||||
|
|
||||||
err = handler.Refresh(newTimeoutCtx(t, ctx))
|
err = handler.Refresh(testutil.ContextWithTimeout(t, testTimeout))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(5), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(5), upstreamRequestsCount.Load())
|
||||||
|
|
||||||
err = handler.ServeDNS(newTimeoutCtx(t, ctx), rw, req)
|
err = handler.ServeDNS(testutil.ContextWithTimeout(t, testTimeout), rw, req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(6), upstreamRequestsCount.Load())
|
assert.Equal(t, int64(6), upstreamRequestsCount.Load())
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func TestUpstreamPlain_Exchange(t *testing.T) {
|
|||||||
defer log.OnCloserError(u, log.DEBUG)
|
defer log.OnCloserError(u, log.DEBUG)
|
||||||
|
|
||||||
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
req := dnsservertest.CreateMessage("example.org.", dns.TypeA)
|
||||||
res, nw, err := u.Exchange(newTimeoutCtx(t, context.Background()), req)
|
res, nw, err := u.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, res)
|
require.NotNil(t, res)
|
||||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||||
@ -95,9 +95,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer log.OnCloserError(uUDP, log.DEBUG)
|
defer log.OnCloserError(uUDP, log.DEBUG)
|
||||||
|
|
||||||
ctx := context.Background()
|
res, nw, err := uUDP.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||||
|
|
||||||
res, nw, err := uUDP.Exchange(newTimeoutCtx(t, ctx), req)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dnsservertest.RequireResponse(t, req, res, 0, dns.RcodeSuccess, true)
|
dnsservertest.RequireResponse(t, req, res, 0, dns.RcodeSuccess, true)
|
||||||
|
|
||||||
@ -110,7 +108,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer log.OnCloserError(uTCP, log.DEBUG)
|
defer log.OnCloserError(uTCP, log.DEBUG)
|
||||||
|
|
||||||
res, nw, err = uTCP.Exchange(newTimeoutCtx(t, ctx), req)
|
res, nw, err = uTCP.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||||
|
|
||||||
@ -124,7 +122,7 @@ func TestUpstreamPlain_Exchange_truncated(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer log.OnCloserError(uAny, log.DEBUG)
|
defer log.OnCloserError(uAny, log.DEBUG)
|
||||||
|
|
||||||
res, nw, err = uAny.Exchange(newTimeoutCtx(t, ctx), req)
|
res, nw, err = uAny.Exchange(testutil.ContextWithTimeout(t, testTimeout), req)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
dnsservertest.RequireResponse(t, req, res, 1, dns.RcodeSuccess, false)
|
||||||
|
|
||||||
@ -165,7 +163,8 @@ func TestUpstreamPlain_Exchange_fallbackFail(t *testing.T) {
|
|||||||
var resp *dns.Msg
|
var resp *dns.Msg
|
||||||
var err error
|
var err error
|
||||||
go func() {
|
go func() {
|
||||||
resp, _, err = u.Exchange(newTimeoutCtx(t, context.Background()), req)
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||||
|
resp, _, err = u.Exchange(ctx, req)
|
||||||
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -266,7 +265,8 @@ func TestUpstreamPlain_Exchange_fallbackSuccess(t *testing.T) {
|
|||||||
var actualResp *dns.Msg
|
var actualResp *dns.Msg
|
||||||
var err error
|
var err error
|
||||||
go func() {
|
go func() {
|
||||||
actualResp, _, err = u.Exchange(newTimeoutCtx(t, context.Background()), clonedReq)
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||||
|
actualResp, _, err = u.Exchange(ctx, clonedReq)
|
||||||
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
testutil.RequireSend(pt, respCh, struct{}{}, testTimeout)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -1,44 +1,45 @@
|
|||||||
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
module github.com/AdguardTeam/AdGuardDNS/internal/dnsserver
|
||||||
|
|
||||||
go 1.21.8
|
go 1.22.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/golibs v0.20.1
|
github.com/AdguardTeam/golibs v0.23.2
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7
|
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||||
github.com/ameshkov/dnsstamps v1.0.3
|
github.com/ameshkov/dnsstamps v1.0.3
|
||||||
github.com/bluele/gcache v0.0.2
|
github.com/bluele/gcache v0.0.2
|
||||||
github.com/miekg/dns v1.1.58
|
github.com/miekg/dns v1.1.58
|
||||||
github.com/panjf2000/ants/v2 v2.9.0
|
github.com/panjf2000/ants/v2 v2.9.1
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.19.0
|
||||||
github.com/quic-go/quic-go v0.41.0
|
github.com/quic-go/quic-go v0.42.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
|
||||||
golang.org/x/net v0.21.0
|
golang.org/x/net v0.24.0
|
||||||
golang.org/x/sys v0.17.0
|
golang.org/x/sys v0.19.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.5.0 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.46.0 // indirect
|
github.com/prometheus/common v0.52.3 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.13.0 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/crypto v0.19.0 // indirect
|
golang.org/x/crypto v0.22.0 // indirect
|
||||||
golang.org/x/mod v0.15.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/tools v0.18.0 // indirect
|
golang.org/x/tools v0.20.0 // indirect
|
||||||
google.golang.org/protobuf v1.32.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
github.com/AdguardTeam/golibs v0.20.1 h1:ol8qLjWGZhU9paMMwN+OLWVTUigGsXa29iVTyd62VKY=
|
github.com/AdguardTeam/golibs v0.23.2 h1:rMjYantwtQ39e8G4zBQ6ZLlm4s3XH30Bc9VxhoOHwao=
|
||||||
github.com/AdguardTeam/golibs v0.20.1/go.mod h1:bgcMgRviCKyU6mkrX+RtT/OsKPFzyppelfRsksMG3KU=
|
github.com/AdguardTeam/golibs v0.23.2/go.mod h1:o9i55Sx6v7qogRQeqaBfmLbC/pZqeMBWi015U5PTDY0=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7 h1:aEitLIR8HcxVodZ79mgRcCiC0A0I5kZPBuWGFwwulAw=
|
github.com/ameshkov/dnscrypt/v2 v2.3.0 h1:pDXDF7eFa6Lw+04C0hoMh8kCAQM8NwUdFEllSP2zNLs=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.7/go.mod h1:qPWhwz6FdSmuK7W4sMyvogrez4MWdtzosdqlr0Rg3ow=
|
github.com/ameshkov/dnscrypt/v2 v2.3.0/go.mod h1:N5hDwgx2cNb4Ay7AhvOSKst+eUiOZ/vbKRO9qMpQttE=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||||
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/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||||
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
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=
|
||||||
@ -22,40 +22,40 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
|||||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
|
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||||
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
|
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||||
github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo=
|
github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw=
|
||||||
github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
github.com/panjf2000/ants/v2 v2.9.1/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible h1:IWzUvJ72xMjmrjR9q3H1PF+jwdN0uNQiR2t1BLNalyo=
|
||||||
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.1-0.20191004192108-46f407853014+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
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 v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
||||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
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=
|
||||||
@ -65,29 +65,31 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
|
||||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||||
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
@ -24,7 +24,7 @@ func TestSessionPacketConn(t *testing.T) {
|
|||||||
|
|
||||||
// Try the test multiple times to reduce flakiness due to UDP failures.
|
// Try the test multiple times to reduce flakiness due to UDP failures.
|
||||||
var success4, success6 bool
|
var success4, success6 bool
|
||||||
for i := 0; i < numTries; i++ {
|
for i := range numTries {
|
||||||
var isTimeout4, isTimeout6 bool
|
var isTimeout4, isTimeout6 bool
|
||||||
success4 = t.Run(fmt.Sprintf("ipv4_%d", i), func(t *testing.T) {
|
success4 = t.Run(fmt.Sprintf("ipv4_%d", i), func(t *testing.T) {
|
||||||
isTimeout4 = testSessionPacketConn(t, "udp4", "0.0.0.0:0", net.IP{127, 0, 0, 1})
|
isTimeout4 = testSessionPacketConn(t, "udp4", "0.0.0.0:0", net.IP{127, 0, 0, 1})
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Conn wraps a net.Conn and contains additional info that could be required
|
// Conn wraps a net.Conn and contains additional info that could be required
|
||||||
// by the Pool instance. It can be used directly instead of a net.Conn or you
|
// by the Pool instance. It can be used directly instead of a net.Conn or you
|
||||||
// may choose to use the underlying Conn.Conn instead.
|
// may choose to use the underlying Conn.Conn instead.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
// ErrClosed indicates that the Pool is closed and cannot be used anymore.
|
// ErrClosed indicates that the Pool is closed and cannot be used anymore.
|
||||||
const ErrClosed = errors.Error("the pool is closed")
|
const ErrClosed = errors.Error("the pool is closed")
|
||||||
|
|
||||||
// Factory is a type for the Pool's factory method. Factory implementation
|
// Factory is a type for the Pool's factory method. Factory implementation
|
||||||
// must use the context's deadline if it's specified.
|
// must use the context's deadline if it's specified.
|
||||||
type Factory func(ctx context.Context) (conn net.Conn, err error)
|
type Factory func(ctx context.Context) (conn net.Conn, err error)
|
||||||
|
|
||||||
@ -35,8 +35,8 @@ type Pool struct {
|
|||||||
factory Factory
|
factory Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPool creates a new Pool instance. maxCapacity configures the maximum
|
// NewPool creates a new Pool instance. maxCapacity configures the maximum
|
||||||
// number of idle connections in the pool. If the pool is full,
|
// number of idle connections in the pool. If the pool is full,
|
||||||
// Put will close the connection instead of adding it to the pool.
|
// Put will close the connection instead of adding it to the pool.
|
||||||
func NewPool(maxCapacity int, factory Factory) (p *Pool) {
|
func NewPool(maxCapacity int, factory Factory) (p *Pool) {
|
||||||
return &Pool{
|
return &Pool{
|
||||||
@ -45,7 +45,7 @@ func NewPool(maxCapacity int, factory Factory) (p *Pool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns a free connection from the pool. If there are no connections it
|
// Get returns a free connection from the pool. If there are no connections it
|
||||||
// will use the Factory method to create a new one.
|
// will use the Factory method to create a new one.
|
||||||
func (p *Pool) Get(ctx context.Context) (conn *Conn, err error) {
|
func (p *Pool) Get(ctx context.Context) (conn *Conn, err error) {
|
||||||
p.connsChanMu.RLock()
|
p.connsChanMu.RLock()
|
||||||
@ -80,7 +80,7 @@ func (p *Pool) Get(ctx context.Context) (conn *Conn, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put puts the connection back to the pool. If the pool is closed,
|
// Put puts the connection back to the pool. If the pool is closed,
|
||||||
// the connection will be simply closed instead.
|
// the connection will be simply closed instead.
|
||||||
func (p *Pool) Put(conn *Conn) (err error) {
|
func (p *Pool) Put(conn *Conn) (err error) {
|
||||||
p.connsChanMu.RLock()
|
p.connsChanMu.RLock()
|
||||||
@ -101,7 +101,7 @@ func (p *Pool) Put(conn *Conn) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the Pool. After that it cannot be used anymore, every method
|
// Close closes the Pool. After that it cannot be used anymore, every method
|
||||||
// will return ErrClosed.
|
// will return ErrClosed.
|
||||||
func (p *Pool) Close() (err error) {
|
func (p *Pool) Close() (err error) {
|
||||||
p.connsChanMu.Lock()
|
p.connsChanMu.Lock()
|
||||||
@ -126,7 +126,7 @@ func (p *Pool) Close() (err error) {
|
|||||||
return errors.Annotate(errors.Join(errs...), "closing pool: %w")
|
return errors.Annotate(errors.Join(errs...), "closing pool: %w")
|
||||||
}
|
}
|
||||||
|
|
||||||
// closeConn is used when the pool is closed. In this case we attempt to close
|
// closeConn is used when the pool is closed. In this case we attempt to close
|
||||||
// the connection immediately.
|
// the connection immediately.
|
||||||
func (p *Pool) closeConn(conn *Conn) (err error) {
|
func (p *Pool) closeConn(conn *Conn) (err error) {
|
||||||
err = conn.Close()
|
err = conn.Close()
|
||||||
|
@ -29,7 +29,7 @@ func TestCacheMetricsListener_integration_cache(t *testing.T) {
|
|||||||
|
|
||||||
// Pass 10 requests through the middleware. This way we'll increment and
|
// Pass 10 requests through the middleware. This way we'll increment and
|
||||||
// set both hits and misses.
|
// set both hits and misses.
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
||||||
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
||||||
StartTime: time.Now(),
|
StartTime: time.Now(),
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func TestInitSyncMap(t *testing.T) {
|
func TestInitSyncMap(t *testing.T) {
|
||||||
numCalls := atomic.Uint32{}
|
numCalls := atomic.Uint32{}
|
||||||
m := newInitSyncMap[int, int](func(k int) (v int) {
|
m := newInitSyncMap(func(k int) (v int) {
|
||||||
numCalls.Add(1)
|
numCalls.Add(1)
|
||||||
|
|
||||||
return k + 1
|
return k + 1
|
||||||
@ -26,13 +26,13 @@ func TestInitSyncMap(t *testing.T) {
|
|||||||
|
|
||||||
results := make(chan int, n)
|
results := make(chan int, n)
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
go func() {
|
go func() {
|
||||||
results <- m.get(key)
|
results <- m.get(key)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for range n {
|
||||||
got, _ := testutil.RequireReceive(t, results, 1*time.Second)
|
got, _ := testutil.RequireReceive(t, results, 1*time.Second)
|
||||||
assert.Equal(t, want, got)
|
assert.Equal(t, want, got)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func TestRateLimiterMetricsListener_integration_cache(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Pass 10 requests through the middleware.
|
// Pass 10 requests through the middleware.
|
||||||
for i := 0; i < 10; i++ {
|
for i := range 10 {
|
||||||
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
ctx := dnsserver.ContextWithServerInfo(context.Background(), testServerInfo)
|
||||||
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
ctx = dnsserver.ContextWithRequestInfo(ctx, &dnsserver.RequestInfo{
|
||||||
StartTime: time.Now(),
|
StartTime: time.Now(),
|
||||||
@ -73,7 +73,7 @@ func BenchmarkRateLimitMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnAllowlisted", func(b *testing.B) {
|
b.Run("OnAllowlisted", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnAllowlisted(ctx, req, rw)
|
l.OnAllowlisted(ctx, req, rw)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -81,7 +81,7 @@ func BenchmarkRateLimitMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnRateLimited", func(b *testing.B) {
|
b.Run("OnRateLimited", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnRateLimited(ctx, req, rw)
|
l.OnRateLimited(ctx, req, rw)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -48,7 +48,7 @@ func TestServerMetricsListener_integration_requestLifetime(t *testing.T) {
|
|||||||
addr := srv.LocalUDPAddr().String()
|
addr := srv.LocalUDPAddr().String()
|
||||||
|
|
||||||
// Pass 10 requests to make the test less flaky.
|
// Pass 10 requests to make the test less flaky.
|
||||||
for i := 0; i < 10; i++ {
|
for range 10 {
|
||||||
res, _, exchErr := c.Exchange(req, addr)
|
res, _, exchErr := c.Exchange(req, addr)
|
||||||
require.NoError(t, exchErr)
|
require.NoError(t, exchErr)
|
||||||
require.NotNil(t, res)
|
require.NotNil(t, res)
|
||||||
@ -96,7 +96,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnRequest", func(b *testing.B) {
|
b.Run("OnRequest", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnRequest(ctx, info, rw)
|
l.OnRequest(ctx, info, rw)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -104,7 +104,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnInvalidMsg", func(b *testing.B) {
|
b.Run("OnInvalidMsg", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnInvalidMsg(ctx)
|
l.OnInvalidMsg(ctx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -112,7 +112,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnError", func(b *testing.B) {
|
b.Run("OnError", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnError(ctx, nil)
|
l.OnError(ctx, nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -120,7 +120,7 @@ func BenchmarkServerMetricsListener(b *testing.B) {
|
|||||||
b.Run("OnPanic", func(b *testing.B) {
|
b.Run("OnPanic", func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
l.OnPanic(ctx, nil)
|
l.OnPanic(ctx, nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -85,7 +85,7 @@ func (p Protocol) IsStdEncrypted() (ok bool) {
|
|||||||
// Used for a kind of validation.
|
// Used for a kind of validation.
|
||||||
type Network string
|
type Network string
|
||||||
|
|
||||||
// Network enum members. Note that we use "tcp" and "udp" strings so that
|
// Network enum members. Note that we use "tcp" and "udp" strings so that
|
||||||
// we could use these constants when calling golang net package functions.
|
// we could use these constants when calling golang net package functions.
|
||||||
const (
|
const (
|
||||||
NetworkTCP Network = "tcp"
|
NetworkTCP Network = "tcp"
|
||||||
|
@ -12,8 +12,6 @@ import (
|
|||||||
cache "github.com/patrickmn/go-cache"
|
cache "github.com/patrickmn/go-cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Backoff Rate Limiter
|
|
||||||
|
|
||||||
// BackoffConfig is the configuration structure for a backoff rate limiter.
|
// BackoffConfig is the configuration structure for a backoff rate limiter.
|
||||||
type BackoffConfig struct {
|
type BackoffConfig struct {
|
||||||
// Allowlist defines which IP networks are excluded from rate limiting.
|
// Allowlist defines which IP networks are excluded from rate limiting.
|
||||||
@ -158,9 +156,8 @@ func validateAddr(addr netip.Addr) (err error) {
|
|||||||
|
|
||||||
// CountResponses implements the Interface interface for *Backoff.
|
// CountResponses implements the Interface interface for *Backoff.
|
||||||
func (l *Backoff) CountResponses(ctx context.Context, resp *dns.Msg, ip netip.Addr) {
|
func (l *Backoff) CountResponses(ctx context.Context, resp *dns.Msg, ip netip.Addr) {
|
||||||
respLimit := l.respSzEst
|
estRespNum := resp.Len() / l.respSzEst
|
||||||
respSize := resp.Len()
|
for range estRespNum {
|
||||||
for i := 0; i < respSize/respLimit; i++ {
|
|
||||||
_, _, _ = l.IsRateLimited(ctx, resp, ip)
|
_, _, _ = l.IsRateLimited(ctx, resp, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func TestRatelimitMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
for i := 0; i < tc.reqsNum; i++ {
|
for range tc.reqsNum {
|
||||||
nrw := dnsserver.NewNonWriterResponseWriter(
|
nrw := dnsserver.NewNonWriterResponseWriter(
|
||||||
&net.UDPAddr{IP: []byte{1, 2, 3, 4}},
|
&net.UDPAddr{IP: []byte{1, 2, 3, 4}},
|
||||||
tc.remoteAddr,
|
tc.remoteAddr,
|
||||||
|
@ -268,7 +268,7 @@ func (s *ServerBase) dispose(rw ResponseWriter, resp *dns.Msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// serveDNSMsgInternal serves the DNS request and uses recorder as a
|
// serveDNSMsgInternal serves the DNS request and uses recorder as a
|
||||||
// ResponseWriter. This method is supposed to be called from serveDNSMsg,
|
// ResponseWriter. This method is supposed to be called from serveDNSMsg,
|
||||||
// the recorded response is used for counting metrics.
|
// the recorded response is used for counting metrics.
|
||||||
func (s *ServerBase) serveDNSMsgInternal(
|
func (s *ServerBase) serveDNSMsgInternal(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
@ -61,14 +61,13 @@ func BenchmarkServeDNS(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
_, err = conn.Write(msg)
|
_, err = conn.Write(msg)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
err = readMsg(resBuf, tc.network, conn)
|
err = readMsg(resBuf, tc.network, conn)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
}
|
}
|
||||||
b.StopTimer()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +129,7 @@ func BenchmarkServeTLS(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
_, err = conn.Write(msg)
|
_, err = conn.Write(msg)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
@ -147,7 +146,6 @@ func BenchmarkServeTLS(b *testing.B) {
|
|||||||
|
|
||||||
require.GreaterOrEqual(b, n, dnsserver.DNSHeaderSize)
|
require.GreaterOrEqual(b, n, dnsserver.DNSHeaderSize)
|
||||||
}
|
}
|
||||||
b.StopTimer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkServeDoH(b *testing.B) {
|
func BenchmarkServeDoH(b *testing.B) {
|
||||||
@ -207,7 +205,7 @@ func BenchmarkServeDoH(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
var res *http.Response
|
var res *http.Response
|
||||||
res, err = client.Do(req)
|
res, err = client.Do(req)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
@ -271,13 +269,12 @@ func BenchmarkServeDNSCrypt(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
var resp *dns.Msg
|
var resp *dns.Msg
|
||||||
resp, err = client.ExchangeConn(conn, req, ri)
|
resp, err = client.ExchangeConn(conn, req, ri)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
require.True(b, resp.Response)
|
require.True(b, resp.Response)
|
||||||
}
|
}
|
||||||
b.StopTimer()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,10 +309,9 @@ func BenchmarkServeQUIC(b *testing.B) {
|
|||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for range b.N {
|
||||||
resp := requireSendQUICMessage(b, sess, req)
|
resp := requireSendQUICMessage(b, sess, req)
|
||||||
require.NotNil(b, resp)
|
require.NotNil(b, resp)
|
||||||
require.True(b, resp.Response)
|
require.True(b, resp.Response)
|
||||||
}
|
}
|
||||||
b.StopTimer()
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user