From 17c41eb6228290f9542dc3d97c8d5700a08cd459 Mon Sep 17 00:00:00 2001 From: sbwml Date: Thu, 28 Sep 2023 17:19:28 +0800 Subject: [PATCH] mosdns: bump to 5.2.1 --- mosdns/Makefile | 8 +- mosdns/patches/100-update-dependencies.patch | 485 ------ mosdns/patches/101-fix-nftset-mask-667.patch | 60 - ...102-server-simplify-udp-oob-handling.patch | 350 ---- mosdns/patches/103-use-go-bytes-pool.patch | 475 ----- mosdns/patches/104-fixed-712.patch | 46 - mosdns/patches/105-fixed-udp-oob-buf.patch | 43 - mosdns/patches/106-fixed-707.patch | 151 -- mosdns/patches/107-add-doq-upstream.patch | 426 ----- ...orkaround-recover-from-0rtt-rejected.patch | 47 - .../109-upgrade-bytesPool-fixed-714.patch | 58 - mosdns/patches/110-fixed-715.patch | 45 - ...server-decoupling-from-query_context.patch | 639 ------- ...-exit-udp-server-on-tempory-read-err.patch | 31 - ...13-pool-fixed-bytes-pool-size-was-1k.patch | 25 - ...xed-PackTCPBuffer-always-re-allocate.patch | 32 - ...-let-WriteMsgToTCP-use-PackTCPBuffer.patch | 31 - ...m-switch-to-self-implement-bootstrap.patch | 1540 ----------------- ...-send-STREAM-FIN-after-query-is-sent.patch | 32 - mosdns/patches/200-add-debug-log-again.patch | 68 - ...patch => 201-compatible-with-go1.20.patch} | 74 +- ...-to-Debug-in-bootstrap-address-updat.patch | 25 + ...for-bad-request-in-ServeHTTP-handler.patch | 24 + ...Fisher-Yates-shuffle-algorithm-to-r.patch} | 8 +- ...logtime.patch => 205-format-logtime.patch} | 6 +- 25 files changed, 84 insertions(+), 4645 deletions(-) delete mode 100644 mosdns/patches/100-update-dependencies.patch delete mode 100644 mosdns/patches/101-fix-nftset-mask-667.patch delete mode 100644 mosdns/patches/102-server-simplify-udp-oob-handling.patch delete mode 100644 mosdns/patches/103-use-go-bytes-pool.patch delete mode 100644 mosdns/patches/104-fixed-712.patch delete mode 100644 mosdns/patches/105-fixed-udp-oob-buf.patch delete mode 100644 mosdns/patches/106-fixed-707.patch delete mode 100644 mosdns/patches/107-add-doq-upstream.patch delete mode 100644 mosdns/patches/108-workaround-recover-from-0rtt-rejected.patch delete mode 100644 mosdns/patches/109-upgrade-bytesPool-fixed-714.patch delete mode 100644 mosdns/patches/110-fixed-715.patch delete mode 100644 mosdns/patches/111-pkg-server-decoupling-from-query_context.patch delete mode 100644 mosdns/patches/112-server-don-t-exit-udp-server-on-tempory-read-err.patch delete mode 100644 mosdns/patches/113-pool-fixed-bytes-pool-size-was-1k.patch delete mode 100644 mosdns/patches/114-pool-fixed-PackTCPBuffer-always-re-allocate.patch delete mode 100644 mosdns/patches/115-dnsutils-let-WriteMsgToTCP-use-PackTCPBuffer.patch delete mode 100644 mosdns/patches/116-upstream-switch-to-self-implement-bootstrap.patch delete mode 100644 mosdns/patches/125-upstream-doq-send-STREAM-FIN-after-query-is-sent.patch delete mode 100644 mosdns/patches/200-add-debug-log-again.patch rename mosdns/patches/{203-compatible-with-go1.20.patch => 201-compatible-with-go1.20.patch} (62%) create mode 100644 mosdns/patches/202-change-log-level-to-Debug-in-bootstrap-address-updat.patch create mode 100644 mosdns/patches/203-add-response-for-bad-request-in-ServeHTTP-handler.patch rename mosdns/patches/{201-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch => 204-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch} (89%) rename mosdns/patches/{202-format-logtime.patch => 205-format-logtime.patch} (91%) diff --git a/mosdns/Makefile b/mosdns/Makefile index a37fa7c..9885042 100644 --- a/mosdns/Makefile +++ b/mosdns/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mosdns -PKG_VERSION:=5.1.3 -PKG_RELEASE:=$(AUTORELEASE) +PKG_VERSION:=5.2.1 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=7db89b2399ace81e86b53e95e5260e55778ad5e6e8dd82a73dd6989dcd2e0eda +PKG_HASH:=f6ed7c29408f4db69f8b5b9fa041e77b2460e561fc889116edb8f6021fad966a PKG_LICENSE:=GPL-3.0 PKG_LICENSE_FILE:=LICENSE @@ -22,7 +22,7 @@ PKG_USE_MIPS16:=0 PKG_BUILD_FLAGS:=no-mips16 GO_PKG:=github.com/IrineSistiana/mosdns -GO_PKG_LDFLAGS_X:=main.version=v$(PKG_VERSION)-$(PKG_RELEASE) +GO_PKG_LDFLAGS_X:=main.version=v$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk diff --git a/mosdns/patches/100-update-dependencies.patch b/mosdns/patches/100-update-dependencies.patch deleted file mode 100644 index 1e6267d..0000000 --- a/mosdns/patches/100-update-dependencies.patch +++ /dev/null @@ -1,485 +0,0 @@ -From 5bb7b776f8b5aba1b23ee5337e2ed3b8a1a79ccd Mon Sep 17 00:00:00 2001 -From: sbwml -Date: Fri, 25 Aug 2023 09:19:37 +0800 -Subject: [PATCH 01/10] update dependencies - ---- - go.mod | 70 +++++++++--------- - go.sum | 156 ++++++++++++++++++++------------------- - pkg/upstream/upstream.go | 23 +++--- - 3 files changed, 128 insertions(+), 121 deletions(-) - -diff --git a/go.mod b/go.mod -index 2212cd3..b56078b 100644 ---- a/go.mod -+++ b/go.mod -@@ -1,28 +1,30 @@ - module github.com/IrineSistiana/mosdns/v5 - --go 1.19 -+go 1.21 -+ -+toolchain go1.21.1 - - require ( -- github.com/go-chi/chi/v5 v5.0.8 -+ github.com/go-chi/chi/v5 v5.0.10 - github.com/google/nftables v0.1.0 - github.com/kardianos/service v1.2.2 -- github.com/klauspost/compress v1.16.3 -- github.com/miekg/dns v1.1.52 -+ github.com/klauspost/compress v1.16.7 -+ github.com/miekg/dns v1.1.56 - github.com/mitchellh/mapstructure v1.5.0 - github.com/nadoo/ipset v0.5.0 -- github.com/prometheus/client_golang v1.14.0 -- github.com/quic-go/quic-go v0.33.0 -- github.com/spf13/cobra v1.6.1 -- github.com/spf13/viper v1.15.0 -- github.com/stretchr/testify v1.8.1 -+ github.com/prometheus/client_golang v1.16.0 -+ github.com/quic-go/quic-go v0.38.1 -+ github.com/spf13/cobra v1.7.0 -+ github.com/spf13/viper v1.16.0 -+ github.com/stretchr/testify v1.8.4 - github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559 -- go.uber.org/zap v1.24.0 -- go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 -- golang.org/x/exp v0.0.0-20230314191032-db074128a8ec -- golang.org/x/net v0.8.0 -- golang.org/x/sync v0.1.0 -- golang.org/x/sys v0.6.0 -- google.golang.org/protobuf v1.29.1 -+ go.uber.org/zap v1.26.0 -+ go4.org/netipx v0.0.0-20230824141953-6213f710f925 -+ golang.org/x/exp v0.0.0-20230905200255-921286631fa9 -+ golang.org/x/net v0.15.0 -+ golang.org/x/sync v0.3.0 -+ golang.org/x/sys v0.12.0 -+ google.golang.org/protobuf v1.31.0 - ) - - replace github.com/nadoo/ipset v0.5.0 => github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a -@@ -32,39 +34,37 @@ require ( - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect -- github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect -+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.5.9 // indirect -- github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect -+ github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/native v1.1.0 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect -- github.com/mdlayher/netlink v1.7.1 // indirect -- github.com/mdlayher/socket v0.4.0 // indirect -- github.com/onsi/ginkgo/v2 v2.9.1 // indirect -- github.com/pelletier/go-toml/v2 v2.0.7 // indirect -+ github.com/mdlayher/netlink v1.7.2 // indirect -+ github.com/mdlayher/socket v0.5.0 // indirect -+ github.com/onsi/ginkgo/v2 v2.12.0 // indirect -+ github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect -- github.com/prometheus/client_model v0.3.0 // indirect -- github.com/prometheus/common v0.42.0 // indirect -- github.com/prometheus/procfs v0.9.0 // indirect -+ github.com/prometheus/client_model v0.4.0 // indirect -+ github.com/prometheus/common v0.44.0 // indirect -+ github.com/prometheus/procfs v0.11.1 // indirect - github.com/quic-go/qpack v0.4.0 // indirect -- github.com/quic-go/qtls-go1-19 v0.2.1 // indirect -- github.com/quic-go/qtls-go1-20 v0.1.1 // indirect -+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect - github.com/spf13/afero v1.9.5 // indirect -- github.com/spf13/cast v1.5.0 // indirect -+ github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect -- github.com/subosito/gotenv v1.4.2 // indirect -+ github.com/subosito/gotenv v1.6.0 // indirect - github.com/vishvananda/netns v0.0.1 // indirect -- go.uber.org/atomic v1.10.0 // indirect -- go.uber.org/multierr v1.10.0 // indirect -- golang.org/x/crypto v0.7.0 // indirect -- golang.org/x/mod v0.9.0 // indirect -- golang.org/x/text v0.8.0 // indirect -- golang.org/x/tools v0.7.0 // indirect -+ go.uber.org/multierr v1.11.0 // indirect -+ golang.org/x/crypto v0.13.0 // indirect -+ golang.org/x/mod v0.12.0 // indirect -+ golang.org/x/text v0.13.0 // indirect -+ golang.org/x/tools v0.13.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - ) -diff --git a/go.sum b/go.sum -index 960ad98..633f864 100644 ---- a/go.sum -+++ b/go.sum -@@ -40,7 +40,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 - github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a h1:GQdh/h0q0ni3L//CXusyk+7QdhBL289vdNaes1WKkHI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ= --github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= - 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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -@@ -63,17 +62,19 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m - github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= - github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= - github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= --github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -+github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= - github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= - github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= --github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= --github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -+github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -+github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= - github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= - github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= - github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= --github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= --github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= --github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -+github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -+github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -+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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= - github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= - github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -@@ -133,8 +134,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf - github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= - github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= - github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= --github.com/google/pprof v0.0.0-20230309165930-d61513b1440d h1:um9/pc7tKMINFfP1eE7Wv6PRGXlcCSJkVajF7KJw3uQ= --github.com/google/pprof v0.0.0-20230309165930-d61513b1440d/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= -+github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= -+github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= - github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= - github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= - github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -@@ -146,7 +147,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= - github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= - github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= - github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= --github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= - github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= - github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= - github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= -@@ -156,81 +156,83 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X - github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60= - github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= - github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= --github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= --github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -+github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= - github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= - github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= --github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= - github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= - github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= - github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= - github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= - github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= - github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= - github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= --github.com/mdlayher/netlink v1.7.1 h1:FdUaT/e33HjEXagwELR8R3/KL1Fq5x3G5jgHLp/BTmg= --github.com/mdlayher/netlink v1.7.1/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ= --github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= --github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= --github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c= --github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= -+github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= -+github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= -+github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI= -+github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI= -+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= -+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= - github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= - github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= --github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= --github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= --github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk= --github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= --github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= --github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -+github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -+github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= -+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -+github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -+github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -+github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= - github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= - github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= - 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/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= --github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -+github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -+github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= - github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= --github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= --github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= --github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= --github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= --github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= --github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -+github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -+github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -+github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -+github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -+github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -+github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= - 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/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= --github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= --github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= --github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= --github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= --github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= -+github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -+github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= -+github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= - github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= --github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -+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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= - github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= - github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= --github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= --github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= --github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= --github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -+github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -+github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= - github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= - github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= - github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= - github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= --github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= --github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= -+github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -+github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= - github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= - github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= - github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= - github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= - github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= - github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= - github.com/stretchr/testify v1.7.0/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.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= --github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= --github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= --github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= - github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559 h1:NwQroOyW+fpfiUroBzAMqFc6NRwBmvJevoVtEK6gsFE= - github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559/go.mod h1:cAAsePK2e15YDAMJNyOpGYEWNe4sIghTY7gpz4cX/Ik= - github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -@@ -247,15 +249,14 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= - go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= - go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= - go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= --go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= --go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= --go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= --go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= --go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= --go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= --go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= --go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo= --go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y= -+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -+go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -+go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ= -+go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= - golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= - golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= - golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -@@ -263,8 +264,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= - golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= --golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= --golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -+golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= - golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= - golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= - golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -@@ -275,8 +276,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 - golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= - golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= - golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= --golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0= --golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -+golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -+golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= - golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= - golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= - golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -@@ -301,8 +302,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= - golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= - golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= - golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= --golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= --golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -+golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= - golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= - golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= - golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -@@ -336,8 +337,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= - golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= - golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= --golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= --golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -+golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= - golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= - golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= - golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -@@ -358,8 +359,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ - golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= - golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= --golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= --golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= - golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= - golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= - golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -@@ -401,8 +402,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc - golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= - golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= - golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= --golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= --golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -+golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= - golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= - golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= - golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -@@ -412,8 +413,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= - golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= - golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= - golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= --golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= --golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= - golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= - golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= - golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -@@ -465,8 +466,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f - golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= - golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= - golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= --golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= --golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -+golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= - golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= - golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -@@ -561,11 +562,12 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj - google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= - google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= - google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= --google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM= --google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= - gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= - gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= - gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= - gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -diff --git a/pkg/upstream/upstream.go b/pkg/upstream/upstream.go -index d0fdc74..8486563 100644 ---- a/pkg/upstream/upstream.go -+++ b/pkg/upstream/upstream.go -@@ -23,6 +23,14 @@ import ( - "context" - "crypto/tls" - "fmt" -+ "io" -+ "net" -+ "net/http" -+ "net/url" -+ "strconv" -+ "strings" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/mlog" - "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" - "github.com/IrineSistiana/mosdns/v5/pkg/upstream/bootstrap" -@@ -33,13 +41,6 @@ import ( - "github.com/quic-go/quic-go/http3" - "go.uber.org/zap" - "golang.org/x/net/http2" -- "io" -- "net" -- "net/http" -- "net/url" -- "strconv" -- "strings" -- "time" - ) - - const ( -@@ -233,7 +234,10 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - if err != nil { - return nil, fmt.Errorf("failed to init udp socket for quic") - } -- addonCloser = conn -+ qt := &quic.Transport{ -+ Conn: conn, -+ } -+ addonCloser = qt - t = &http3.RoundTripper{ - TLSClientConfig: opt.TLSConfig, - QuicConfig: &quic.Config{ -@@ -248,7 +252,8 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - if err != nil { - return nil, err - } -- return quic.DialEarlyContext(ctx, conn, ua, addrURL.Host, tlsCfg, cfg) -+ -+ return qt.DialEarly(ctx, ua, tlsCfg, cfg) - }, - } - } else { --- -2.34.8 - diff --git a/mosdns/patches/101-fix-nftset-mask-667.patch b/mosdns/patches/101-fix-nftset-mask-667.patch deleted file mode 100644 index 6f1cfcd..0000000 --- a/mosdns/patches/101-fix-nftset-mask-667.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 854b3e77c36acfe8032e71306d617d40fce19591 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Fri, 16 Jun 2023 14:56:30 +0800 -Subject: [PATCH 02/10] fix #667 - ---- - pkg/nftset_utils/handler.go | 27 +++++++++++++++------------ - 1 file changed, 15 insertions(+), 12 deletions(-) - -diff --git a/pkg/nftset_utils/handler.go b/pkg/nftset_utils/handler.go -index 7403f39..3b79afb 100644 ---- a/pkg/nftset_utils/handler.go -+++ b/pkg/nftset_utils/handler.go -@@ -24,11 +24,12 @@ package nftset_utils - import ( - "errors" - "fmt" -- "github.com/google/nftables" -- "go4.org/netipx" - "net/netip" - "sync" - "time" -+ -+ "github.com/google/nftables" -+ "go4.org/netipx" - ) - - var ( -@@ -113,16 +114,18 @@ func (h *NftSetHandler) AddElems(es ...netip.Prefix) error { - elems = make([]nftables.SetElement, 0, len(es)) - } - -- for _, e := range es { -- if set.Interval && !e.IsSingleIP() { -- r := netipx.RangeOfPrefix(e) -- start := r.From() -- end := r.To() -- elems = append( -- elems, -- nftables.SetElement{Key: start.AsSlice(), IntervalEnd: false}, -- nftables.SetElement{Key: end.Next().AsSlice(), IntervalEnd: true}, -- ) -+ for i, e := range es { -+ if !e.IsValid() { -+ return fmt.Errorf("invalid prefix at index %d", i) -+ } -+ if set.Interval { -+ start := e.Masked().Addr() -+ elems = append(elems, nftables.SetElement{Key: start.AsSlice(), IntervalEnd: false}) -+ -+ end := netipx.PrefixLastIP(e).Next() // may be invalid if end is overflowed -+ if end.IsValid() { -+ elems = append(elems, nftables.SetElement{Key: end.AsSlice(), IntervalEnd: true}) -+ } - } else { - elems = append(elems, nftables.SetElement{Key: e.Addr().AsSlice()}) - } --- -2.34.8 - diff --git a/mosdns/patches/102-server-simplify-udp-oob-handling.patch b/mosdns/patches/102-server-simplify-udp-oob-handling.patch deleted file mode 100644 index cbbc6bc..0000000 --- a/mosdns/patches/102-server-simplify-udp-oob-handling.patch +++ /dev/null @@ -1,350 +0,0 @@ -From f0274e3664a690d8ef1dd05ba7dc68869df7806f Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Thu, 31 Aug 2023 18:09:09 +0800 -Subject: [PATCH 03/10] server: simplify udp oob handling - ---- - pkg/server/udp.go | 71 +++++++--------- - pkg/server/udp_linux.go | 112 +++++++++++-------------- - pkg/server/udp_others.go | 4 +- - plugin/server/udp_server/udp_server.go | 5 +- - 4 files changed, 86 insertions(+), 106 deletions(-) - -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index 45d689c..8980a08 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -22,14 +22,14 @@ package server - import ( - "context" - "fmt" -+ "net" -+ - "github.com/IrineSistiana/mosdns/v5/mlog" - "github.com/IrineSistiana/mosdns/v5/pkg/pool" - "github.com/IrineSistiana/mosdns/v5/pkg/query_context" - "github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler" -- "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/miekg/dns" - "go.uber.org/zap" -- "net" - ) - - type UDPServer struct { -@@ -53,39 +53,31 @@ func (opts *UDPServerOpts) init() { - return - } - --// cmcUDPConn can read and write cmsg. --type cmcUDPConn interface { -- readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) -- writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) --} -- - // ServeUDP starts a server at c. It returns if c had a read error. - // It always returns a non-nil error. --func (s *UDPServer) ServeUDP(c net.PacketConn) error { -+func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - listenerCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - - rb := pool.GetBuf(dns.MaxMsgSize) - defer pool.ReleaseBuf(rb) - -- var cmc cmcUDPConn -- var err error -- uc, ok := c.(*net.UDPConn) -- if ok && uc.LocalAddr().(*net.UDPAddr).IP.IsUnspecified() { -- cmc, err = newCmc(uc) -- if err != nil { -- return fmt.Errorf("failed to control socket cmsg, %w", err) -- } -- } else { -- cmc = newDummyCmc(c) -+ oobReader, oobWriter, err := initOobHandler(c) -+ if err != nil { -+ return fmt.Errorf("failed to init oob handler, %w", err) -+ } -+ var ob []byte -+ if oobReader != nil { -+ ob := pool.GetBuf(1024) -+ defer pool.ReleaseBuf(ob) - } - - for { -- n, localAddr, ifIndex, remoteAddr, err := cmc.readFrom(rb) -+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(rb, ob) - if err != nil { - return fmt.Errorf("unexpected read err: %w", err) - } -- clientAddr := utils.GetAddrFromAddr(remoteAddr) -+ clientAddr := remoteAddr.Addr() - - q := new(dns.Msg) - if err := q.Unpack(rb[:n]); err != nil { -@@ -93,6 +85,15 @@ func (s *UDPServer) ServeUDP(c net.PacketConn) error { - continue - } - -+ var dstIpFromCm net.IP -+ if oobReader != nil { -+ var err error -+ dstIpFromCm, err = oobReader(ob[:oobn]) -+ if err != nil { -+ s.opts.Logger.Error("failed to get dst address from oob", zap.Error(err)) -+ } -+ } -+ - // handle query - go func() { - qCtx := query_context.NewContext(q) -@@ -110,7 +111,12 @@ func (s *UDPServer) ServeUDP(c net.PacketConn) error { - return - } - defer pool.ReleaseBuf(buf) -- if _, err := cmc.writeTo(b, localAddr, ifIndex, remoteAddr); err != nil { -+ var oob []byte -+ -+ if oobWriter != nil && dstIpFromCm != nil { -+ oob = oobWriter(dstIpFromCm) -+ } -+ if _, _, err := c.WriteMsgUDPAddrPort(b, oob, remoteAddr); err != nil { - s.opts.Logger.Warn("failed to write response", zap.Stringer("client", remoteAddr), zap.Error(err)) - } - } -@@ -129,22 +135,5 @@ func getUDPSize(m *dns.Msg) int { - return int(s) - } - --// newDummyCmc returns a dummyCmcWrapper. --func newDummyCmc(c net.PacketConn) cmcUDPConn { -- return dummyCmcWrapper{c: c} --} -- --// dummyCmcWrapper is just a wrapper that implements cmcUDPConn but does not --// write or read any control msg. --type dummyCmcWrapper struct { -- c net.PacketConn --} -- --func (w dummyCmcWrapper) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) { -- n, src, err = w.c.ReadFrom(b) -- return --} -- --func (w dummyCmcWrapper) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) { -- return w.c.WriteTo(b, dst) --} -+type getSrcAddrFromOOB func(oob []byte) (net.IP, error) -+type writeSrcAddrToOOB func(a net.IP) []byte -diff --git a/pkg/server/udp_linux.go b/pkg/server/udp_linux.go -index 4eb466d..9728a39 100644 ---- a/pkg/server/udp_linux.go -+++ b/pkg/server/udp_linux.go -@@ -22,84 +22,71 @@ - package server - - import ( -+ "errors" - "fmt" -+ "net" -+ "os" -+ - "golang.org/x/net/ipv4" - "golang.org/x/net/ipv6" - "golang.org/x/sys/unix" -- "net" -- "os" - ) - --type ipv4cmc struct { -- c *ipv4.PacketConn --} -- --func newIpv4cmc(c *ipv4.PacketConn) *ipv4cmc { -- return &ipv4cmc{c: c} --} -+var ( -+ errCmNoDstAddr = errors.New("control msg does not have dst address") -+) - --func (i *ipv4cmc) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) { -- n, cm, src, err := i.c.ReadFrom(b) -- if cm != nil { -- dst, IfIndex = cm.Dst, cm.IfIndex -+func getOOBFromCM4(oob []byte) (net.IP, error) { -+ var cm ipv4.ControlMessage -+ if err := cm.Parse(oob); err != nil { -+ return nil, err - } -- return --} -- --func (i *ipv4cmc) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) { -- cm := &ipv4.ControlMessage{ -- Src: src, -- IfIndex: IfIndex, -+ if cm.Dst == nil { -+ return nil, errCmNoDstAddr - } -- return i.c.WriteTo(b, cm, dst) -+ return cm.Dst, nil - } - --type ipv6cmc struct { -- c4 *ipv4.PacketConn // ipv4 entrypoint for sending ipv4 packages. -- c6 *ipv6.PacketConn -+func getOOBFromCM6(oob []byte) (net.IP, error) { -+ var cm ipv6.ControlMessage -+ if err := cm.Parse(oob); err != nil { -+ return nil, err -+ } -+ if cm.Dst == nil { -+ return nil, errCmNoDstAddr -+ } -+ return cm.Dst, nil - } - --func newIpv6PacketConn(c4 *ipv4.PacketConn, c6 *ipv6.PacketConn) *ipv6cmc { -- return &ipv6cmc{c4: c4, c6: c6} --} -+func srcIP2Cm(ip net.IP) []byte { -+ if ip4 := ip.To4(); ip4 != nil { -+ return (&ipv4.ControlMessage{ -+ Src: ip, -+ }).Marshal() -+ } - --func (i *ipv6cmc) readFrom(b []byte) (n int, dst net.IP, IfIndex int, src net.Addr, err error) { -- n, cm, src, err := i.c6.ReadFrom(b) -- if cm != nil { -- dst, IfIndex = cm.Dst, cm.IfIndex -+ if ip6 := ip.To16(); ip6 != nil { -+ return (&ipv6.ControlMessage{ -+ Src: ip, -+ }).Marshal() - } -- return -+ -+ return nil - } - --func (i *ipv6cmc) writeTo(b []byte, src net.IP, IfIndex int, dst net.Addr) (n int, err error) { -- if src != nil { -- // If src is ipv4, use IP_PKTINFO instead of IPV6_PKTINFO. -- // Otherwise, sendmsg will raise "invalid argument" error. -- // No official doc found. -- if src4 := src.To4(); src4 != nil { -- cm4 := &ipv4.ControlMessage{ -- Src: src4, -- IfIndex: IfIndex, -- } -- return i.c4.WriteTo(b, cm4, dst) -- } -- } -- cm6 := &ipv6.ControlMessage{ -- Src: src, -- IfIndex: IfIndex, -+func initOobHandler(c *net.UDPConn) (getSrcAddrFromOOB, writeSrcAddrToOOB, error) { -+ if !c.LocalAddr().(*net.UDPAddr).IP.IsUnspecified() { -+ return nil, nil, nil - } -- return i.c6.WriteTo(b, cm6, dst) --} - --func newCmc(c *net.UDPConn) (cmcUDPConn, error) { - sc, err := c.SyscallConn() - if err != nil { -- return nil, err -+ return nil, nil, err - } - -+ var getter getSrcAddrFromOOB -+ var setter writeSrcAddrToOOB - var controlErr error -- var cmc cmcUDPConn -- - if err := sc.Control(func(fd uintptr) { - v, err := unix.GetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_DOMAIN) - if err != nil { -@@ -109,27 +96,30 @@ func newCmc(c *net.UDPConn) (cmcUDPConn, error) { - switch v { - case unix.AF_INET: - c4 := ipv4.NewPacketConn(c) -- if err := c4.SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true); err != nil { -+ if err := c4.SetControlMessage(ipv4.FlagDst, true); err != nil { - controlErr = fmt.Errorf("failed to set ipv4 cmsg flags, %w", err) - } -- cmc = newIpv4cmc(c4) -+ -+ getter = getOOBFromCM4 -+ setter = srcIP2Cm - return - case unix.AF_INET6: - c6 := ipv6.NewPacketConn(c) -- if err := c6.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { -+ if err := c6.SetControlMessage(ipv6.FlagDst, true); err != nil { - controlErr = fmt.Errorf("failed to set ipv6 cmsg flags, %w", err) - } -- cmc = newIpv6PacketConn(ipv4.NewPacketConn(c), c6) -+ getter = getOOBFromCM6 -+ setter = srcIP2Cm - return - default: - controlErr = fmt.Errorf("socket protocol %d is not supported", v) - } - }); err != nil { -- return nil, fmt.Errorf("control fd err, %w", controlErr) -+ return nil, nil, fmt.Errorf("control fd err, %w", controlErr) - } - - if controlErr != nil { -- return nil, fmt.Errorf("failed to set up socket, %w", controlErr) -+ return nil, nil, fmt.Errorf("failed to set up socket, %w", controlErr) - } -- return cmc, nil -+ return getter, setter, nil - } -diff --git a/pkg/server/udp_others.go b/pkg/server/udp_others.go -index 8ce6280..1e42651 100644 ---- a/pkg/server/udp_others.go -+++ b/pkg/server/udp_others.go -@@ -23,6 +23,6 @@ package server - - import "net" - --func newCmc(c *net.UDPConn) (cmcUDPConn, error) { -- return newDummyCmc(c), nil -+func initOobHandler(c *net.UDPConn) (getSrcAddrFromOOB, writeSrcAddrToOOB, error) { -+ return nil, nil, nil - } -diff --git a/plugin/server/udp_server/udp_server.go b/plugin/server/udp_server/udp_server.go -index 9ed94f5..293f720 100644 ---- a/plugin/server/udp_server/udp_server.go -+++ b/plugin/server/udp_server/udp_server.go -@@ -21,11 +21,12 @@ package udp_server - - import ( - "fmt" -+ "net" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" - "github.com/IrineSistiana/mosdns/v5/pkg/server" - "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/IrineSistiana/mosdns/v5/plugin/server/server_utils" -- "net" - ) - - const PluginType = "udp_server" -@@ -71,7 +72,7 @@ func StartServer(bp *coremain.BP, args *Args) (*UdpServer, error) { - } - go func() { - defer c.Close() -- err := s.ServeUDP(c) -+ err := s.ServeUDP(c.(*net.UDPConn)) - bp.M().GetSafeClose().SendCloseSignal(err) - }() - return &UdpServer{ --- -2.34.8 - diff --git a/mosdns/patches/103-use-go-bytes-pool.patch b/mosdns/patches/103-use-go-bytes-pool.patch deleted file mode 100644 index b5ba5df..0000000 --- a/mosdns/patches/103-use-go-bytes-pool.patch +++ /dev/null @@ -1,475 +0,0 @@ -From 9bb813bf50ba0eed3a35acc8f41764613c11687d Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Sun, 17 Sep 2023 08:29:31 +0800 -Subject: [PATCH 04/10] use go-bytes-pool - ---- - go.mod | 1 + - go.sum | 2 + - pkg/dnsutils/net_io.go | 45 +++++---- - pkg/pool/allocator.go | 78 +--------------- - pkg/pool/allocator_test.go | 119 ------------------------ - pkg/pool/msg_buf.go | 4 +- - pkg/pool/msg_buf_test.go | 4 +- - pkg/server/udp.go | 6 +- - pkg/upstream/transport/dns_conn_test.go | 4 +- - plugin/executable/cache/cache.go | 8 +- - 10 files changed, 43 insertions(+), 228 deletions(-) - delete mode 100644 pkg/pool/allocator_test.go - -diff --git a/go.mod b/go.mod -index b56078b..2c359e3 100644 ---- a/go.mod -+++ b/go.mod -@@ -5,6 +5,7 @@ go 1.21 - toolchain go1.21.1 - - require ( -+ github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 - github.com/go-chi/chi/v5 v5.0.10 - github.com/google/nftables v0.1.0 - github.com/kardianos/service v1.2.2 -diff --git a/go.sum b/go.sum -index 633f864..d4bbaa2 100644 ---- a/go.sum -+++ b/go.sum -@@ -38,6 +38,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f - dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= - github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= - github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 h1:5R32cCep3VUDTKf3aurFKfgbvg+RScuBmZsw/DyyXco= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a h1:GQdh/h0q0ni3L//CXusyk+7QdhBL289vdNaes1WKkHI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ= - github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -diff --git a/pkg/dnsutils/net_io.go b/pkg/dnsutils/net_io.go -index 1b8a7b1..8fc769b 100644 ---- a/pkg/dnsutils/net_io.go -+++ b/pkg/dnsutils/net_io.go -@@ -23,9 +23,10 @@ import ( - "encoding/binary" - "errors" - "fmt" -+ "io" -+ - "github.com/IrineSistiana/mosdns/v5/pkg/pool" - "github.com/miekg/dns" -- "io" - ) - - var ( -@@ -35,45 +36,43 @@ var ( - // ReadRawMsgFromTCP reads msg from c in RFC 1035 format (msg is prefixed - // with a two byte length field). - // n represents how many bytes are read from c. --// The returned the []byte should be released by pool.ReleaseBuf. --func ReadRawMsgFromTCP(c io.Reader) ([]byte, int, error) { -- n := 0 -+// The returned the *[]byte should be released by pool.ReleaseBuf. -+func ReadRawMsgFromTCP(c io.Reader) (*[]byte, error) { - h := pool.GetBuf(2) - defer pool.ReleaseBuf(h) -- nh, err := io.ReadFull(c, h) -- n += nh -+ _, err := io.ReadFull(c, *h) -+ - if err != nil { -- return nil, n, err -+ return nil, err - } - - // dns length -- length := binary.BigEndian.Uint16(h) -+ length := binary.BigEndian.Uint16(*h) - if length == 0 { -- return nil, 0, errZeroLenMsg -+ return nil, errZeroLenMsg - } - -- buf := pool.GetBuf(int(length)) -- nm, err := io.ReadFull(c, buf) -- n += nm -+ b := pool.GetBuf(int(length)) -+ _, err = io.ReadFull(c, *b) - if err != nil { -- pool.ReleaseBuf(buf) -- return nil, n, err -+ pool.ReleaseBuf(b) -+ return nil, err - } -- return buf, n, nil -+ return b, nil - } - - // ReadMsgFromTCP reads msg from c in RFC 1035 format (msg is prefixed - // with a two byte length field). - // n represents how many bytes are read from c. - func ReadMsgFromTCP(c io.Reader) (*dns.Msg, int, error) { -- b, n, err := ReadRawMsgFromTCP(c) -+ b, err := ReadRawMsgFromTCP(c) - if err != nil { - return nil, 0, err - } - defer pool.ReleaseBuf(b) - -- m, err := unpackMsgWithDetailedErr(b) -- return m, n, err -+ m, err := unpackMsgWithDetailedErr(*b) -+ return m, len(*b) + 2, err - } - - // WriteMsgToTCP packs and writes m to c in RFC 1035 format. -@@ -96,9 +95,9 @@ func WriteRawMsgToTCP(c io.Writer, b []byte) (n int, err error) { - buf := pool.GetBuf(len(b) + 2) - defer pool.ReleaseBuf(buf) - -- binary.BigEndian.PutUint16(buf[:2], uint16(len(b))) -- copy(buf[2:], b) -- return c.Write(buf) -+ binary.BigEndian.PutUint16((*buf)[:2], uint16(len(b))) -+ copy((*buf)[2:], b) -+ return c.Write((*buf)) - } - - func WriteMsgToUDP(c io.Writer, m *dns.Msg) (int, error) { -@@ -118,12 +117,12 @@ func ReadMsgFromUDP(c io.Reader, bufSize int) (*dns.Msg, int, error) { - - b := pool.GetBuf(bufSize) - defer pool.ReleaseBuf(b) -- n, err := c.Read(b) -+ n, err := c.Read(*b) - if err != nil { - return nil, n, err - } - -- m, err := unpackMsgWithDetailedErr(b[:n]) -+ m, err := unpackMsgWithDetailedErr((*b)[:n]) - return m, n, err - } - -diff --git a/pkg/pool/allocator.go b/pkg/pool/allocator.go -index 0bfc0bc..d8ac4ef 100644 ---- a/pkg/pool/allocator.go -+++ b/pkg/pool/allocator.go -@@ -20,79 +20,11 @@ - package pool - - import ( -- "fmt" -- "math" -- "math/bits" -- "sync" -+ bytesPool "github.com/IrineSistiana/go-bytes-pool" - ) - - // defaultBufPool is an Allocator that has a maximum capacity. --var defaultBufPool = NewAllocator() -- --// GetBuf returns a []byte from pool with most appropriate cap. --// It panics if size < 0. --func GetBuf(size int) []byte { -- return defaultBufPool.Get(size) --} -- --// ReleaseBuf puts the buf to the pool. --func ReleaseBuf(b []byte) { -- defaultBufPool.Release(b) --} -- --type Allocator struct { -- buffers []sync.Pool --} -- --// NewAllocator initiates a []byte Allocator. --// The waste(memory fragmentation) of space allocation is guaranteed to be --// no more than 50%. --func NewAllocator() *Allocator { -- alloc := &Allocator{ -- buffers: make([]sync.Pool, bits.UintSize+1), -- } -- -- for i := range alloc.buffers { -- var bufSize uint -- if i == bits.UintSize { -- bufSize = math.MaxUint -- } else { -- bufSize = 1 << i -- } -- alloc.buffers[i].New = func() any { -- b := make([]byte, bufSize) -- return &b -- } -- } -- return alloc --} -- --// Get returns a []byte from pool with most appropriate cap --func (alloc *Allocator) Get(size int) []byte { -- if size < 0 { -- panic(fmt.Sprintf("invalid slice size %d", size)) -- } -- -- i := shard(size) -- v := alloc.buffers[i].Get() -- buf := v.(*[]byte) -- return (*buf)[0:size] --} -- --// Release releases the buf to the allocatorL. --func (alloc *Allocator) Release(buf []byte) { -- c := cap(buf) -- i := shard(c) -- if c == 0 || c != 1<. -- */ -- --package pool -- --import ( -- "fmt" -- "strconv" -- "testing" --) -- --func TestAllocator_Get(t *testing.T) { -- alloc := NewAllocator() -- tests := []struct { -- size int -- wantCap int -- wantPanic bool -- }{ -- {-1, 0, true}, // invalid -- {0, 1, false}, -- {1, 1, false}, -- {2, 2, false}, -- {12, 16, false}, -- {256, 256, false}, -- {257, 512, false}, -- } -- for _, tt := range tests { -- t.Run(strconv.Itoa(tt.size), func(t *testing.T) { -- if tt.wantPanic { -- defer func() { -- msg := recover() -- if msg == nil { -- t.Error("no panic") -- } -- }() -- } -- -- for i := 0; i < 5; i++ { -- b := alloc.Get(tt.size) -- if len(b) != tt.size { -- t.Fatalf("buffer size, want %d, got %d", tt.size, len(b)) -- } -- if cap(b) != tt.wantCap { -- t.Fatalf("buffer cap, want %d, got %d", tt.wantCap, cap(b)) -- } -- alloc.Release(b) -- } -- }) -- } --} -- --func Test_shard(t *testing.T) { -- tests := []struct { -- size int -- want int -- }{ -- {-1, 0}, -- {0, 0}, -- {1, 0}, -- {2, 1}, -- {3, 2}, -- {4, 2}, -- {5, 3}, -- {8, 3}, -- {1023, 10}, -- {1024, 10}, -- {1025, 11}, -- } -- for _, tt := range tests { -- t.Run(strconv.Itoa(tt.size), func(t *testing.T) { -- if got := shard(tt.size); got != tt.want { -- t.Errorf("shard() = %v, want %v", got, tt.want) -- } -- }) -- } --} -- --func Benchmark_Allocator(b *testing.B) { -- allocator := NewAllocator() -- -- for l := 0; l <= 16; l += 4 { -- bufLen := 1 << l -- b.Run(fmt.Sprintf("length %d", bufLen), func(b *testing.B) { -- b.ReportAllocs() -- for i := 0; i < b.N; i++ { -- buf := allocator.Get(bufLen) -- allocator.Release(buf) -- } -- }) -- } --} -- --func Benchmark_MakeByteSlice(b *testing.B) { -- for l := 0; l <= 8; l++ { -- bufLen := 1 << l -- b.Run(fmt.Sprintf("length %d", bufLen), func(b *testing.B) { -- b.ReportAllocs() -- for i := 0; i < b.N; i++ { -- _ = make([]byte, bufLen) -- } -- }) -- } --} -diff --git a/pkg/pool/msg_buf.go b/pkg/pool/msg_buf.go -index 83eea80..980a08b 100644 ---- a/pkg/pool/msg_buf.go -+++ b/pkg/pool/msg_buf.go -@@ -31,9 +31,9 @@ const packBufSize = 4096 - // PackBuffer packs the dns msg m to wire format. - // Callers should release the buf by calling ReleaseBuf after they have done - // with the wire []byte. --func PackBuffer(m *dns.Msg) (wire, buf []byte, err error) { -+func PackBuffer(m *dns.Msg) (wire []byte, buf *[]byte, err error) { - buf = GetBuf(packBufSize) -- wire, err = m.PackBuffer(buf) -+ wire, err = m.PackBuffer(*buf) - if err != nil { - ReleaseBuf(buf) - return nil, nil, err -diff --git a/pkg/pool/msg_buf_test.go b/pkg/pool/msg_buf_test.go -index 0685864..02d7348 100644 ---- a/pkg/pool/msg_buf_test.go -+++ b/pkg/pool/msg_buf_test.go -@@ -32,7 +32,7 @@ func TestPackBuffer_No_Allocation(t *testing.T) { - t.Fatal(err) - } - -- if cap(wire) != cap(buf) { -- t.Fatalf("wire and buf have different cap, wire %d, buf %d", cap(wire), cap(buf)) -+ if cap(wire) != cap(*buf) { -+ t.Fatalf("wire and buf have different cap, wire %d, buf %d", cap(wire), cap(*buf)) - } - } -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index 8980a08..c1c9aa9 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -73,15 +73,15 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - } - - for { -- n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(rb, ob) -+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, ob) - if err != nil { - return fmt.Errorf("unexpected read err: %w", err) - } - clientAddr := remoteAddr.Addr() - - q := new(dns.Msg) -- if err := q.Unpack(rb[:n]); err != nil { -- s.opts.Logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", rb[:n]), zap.Stringer("from", remoteAddr)) -+ if err := q.Unpack((*rb)[:n]); err != nil { -+ s.opts.Logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", (*rb)[:n]), zap.Stringer("from", remoteAddr)) - continue - } - -diff --git a/pkg/upstream/transport/dns_conn_test.go b/pkg/upstream/transport/dns_conn_test.go -index 8c49131..c677797 100644 ---- a/pkg/upstream/transport/dns_conn_test.go -+++ b/pkg/upstream/transport/dns_conn_test.go -@@ -40,13 +40,13 @@ var ( - c1, c2 := net.Pipe() - go func() { - for { -- m, _, readErr := dnsutils.ReadRawMsgFromTCP(c2) -+ m, readErr := dnsutils.ReadRawMsgFromTCP(c2) - if m != nil { - go func() { - defer pool.ReleaseBuf(m) - latency := time.Millisecond * time.Duration(rand.Intn(20)) - time.Sleep(latency) -- _, _ = dnsutils.WriteRawMsgToTCP(c2, m) -+ _, _ = dnsutils.WriteRawMsgToTCP(c2, *m) - }() - } - if readErr != nil { -diff --git a/plugin/executable/cache/cache.go b/plugin/executable/cache/cache.go -index f67d740..4091b50 100644 ---- a/plugin/executable/cache/cache.go -+++ b/plugin/executable/cache/cache.go -@@ -420,27 +420,27 @@ func (c *Cache) readDump(r io.Reader) (int, error) { - readBlock := func() error { - h := pool.GetBuf(8) - defer pool.ReleaseBuf(h) -- _, err := io.ReadFull(gr, h) -+ _, err := io.ReadFull(gr, *h) - if err != nil { - if errors.Is(err, io.EOF) { - return errReadHeaderEOF - } - return fmt.Errorf("failed to read block header, %w", err) - } -- u := binary.BigEndian.Uint64(h) -+ u := binary.BigEndian.Uint64(*h) - if u > dumpMaximumBlockLength { - return fmt.Errorf("invalid header, block length is big, %d", u) - } - - b := pool.GetBuf(int(u)) - defer pool.ReleaseBuf(b) -- _, err = io.ReadFull(gr, b) -+ _, err = io.ReadFull(gr, *b) - if err != nil { - return fmt.Errorf("failed to read block data, %w", err) - } - - block := new(CacheDumpBlock) -- if err := proto.Unmarshal(b, block); err != nil { -+ if err := proto.Unmarshal(*b, block); err != nil { - return fmt.Errorf("failed to decode block data, %w", err) - } - --- -2.34.8 - diff --git a/mosdns/patches/104-fixed-712.patch b/mosdns/patches/104-fixed-712.patch deleted file mode 100644 index 581f775..0000000 --- a/mosdns/patches/104-fixed-712.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 757ccd6692c93fd7071a9e8011beea3d792dfb9d Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Sun, 17 Sep 2023 19:52:38 +0800 -Subject: [PATCH 05/10] fixed #712 - ---- - plugin/executable/nftset/nftset_linux.go | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/plugin/executable/nftset/nftset_linux.go b/plugin/executable/nftset/nftset_linux.go -index 5d6b0ec..0fc1c8e 100644 ---- a/plugin/executable/nftset/nftset_linux.go -+++ b/plugin/executable/nftset/nftset_linux.go -@@ -24,12 +24,13 @@ package nftset - import ( - "context" - "fmt" -+ "net/netip" -+ - "github.com/IrineSistiana/mosdns/v5/pkg/nftset_utils" - "github.com/IrineSistiana/mosdns/v5/pkg/query_context" - "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/google/nftables" - "github.com/miekg/dns" -- "net/netip" - ) - - type nftSetPlugin struct { -@@ -138,8 +139,12 @@ func (p *nftSetPlugin) addElems(r *dns.Msg) error { - } - - func (p *nftSetPlugin) Close() error { -- _ = p.v6Handler.Close() -- _ = p.v4Handler.Close() -+ if p.v4Handler != nil { -+ _ = p.v4Handler.Close() -+ } -+ if p.v6Handler != nil { -+ _ = p.v6Handler.Close() -+ } - return nil - } - --- -2.34.8 - diff --git a/mosdns/patches/105-fixed-udp-oob-buf.patch b/mosdns/patches/105-fixed-udp-oob-buf.patch deleted file mode 100644 index f39add5..0000000 --- a/mosdns/patches/105-fixed-udp-oob-buf.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 9c235f5aa42fe0dcf410486b199b30dc9e40c998 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Mon, 18 Sep 2023 09:50:44 +0800 -Subject: [PATCH 06/10] fixed udp oob buf - ---- - pkg/server/udp.go | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index c1c9aa9..a1e478b 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -66,14 +66,14 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - if err != nil { - return fmt.Errorf("failed to init oob handler, %w", err) - } -- var ob []byte -+ var ob *[]byte - if oobReader != nil { -- ob := pool.GetBuf(1024) -+ ob = pool.GetBuf(1024) - defer pool.ReleaseBuf(ob) - } - - for { -- n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, ob) -+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, *ob) - if err != nil { - return fmt.Errorf("unexpected read err: %w", err) - } -@@ -88,7 +88,7 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - var dstIpFromCm net.IP - if oobReader != nil { - var err error -- dstIpFromCm, err = oobReader(ob[:oobn]) -+ dstIpFromCm, err = oobReader((*ob)[:oobn]) - if err != nil { - s.opts.Logger.Error("failed to get dst address from oob", zap.Error(err)) - } --- -2.34.8 - diff --git a/mosdns/patches/106-fixed-707.patch b/mosdns/patches/106-fixed-707.patch deleted file mode 100644 index e8635b1..0000000 --- a/mosdns/patches/106-fixed-707.patch +++ /dev/null @@ -1,151 +0,0 @@ -From edd39f198bc34ba443983a277e40e6f87ca38da6 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Mon, 18 Sep 2023 10:36:43 +0800 -Subject: [PATCH 07/10] fixed #707 - ---- - plugin/executable/cache/cache.go | 19 ++++++++++--------- - plugin/executable/cache/dump.pb.go | 18 +++++++++--------- - plugin/executable/cache/dump.proto | 2 +- - 3 files changed, 20 insertions(+), 19 deletions(-) - -diff --git a/plugin/executable/cache/cache.go b/plugin/executable/cache/cache.go -index 4091b50..58162ee 100644 ---- a/plugin/executable/cache/cache.go -+++ b/plugin/executable/cache/cache.go -@@ -24,6 +24,14 @@ import ( - "encoding/binary" - "errors" - "fmt" -+ "io" -+ "net/http" -+ "os" -+ "strconv" -+ "sync" -+ "sync/atomic" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" - "github.com/IrineSistiana/mosdns/v5/pkg/cache" - "github.com/IrineSistiana/mosdns/v5/pkg/pool" -@@ -37,13 +45,6 @@ import ( - "go.uber.org/zap" - "golang.org/x/sync/singleflight" - "google.golang.org/protobuf/proto" -- "io" -- "net/http" -- "os" -- "strconv" -- "sync" -- "sync/atomic" -- "time" - ) - - const ( -@@ -60,7 +61,7 @@ const ( - expiredMsgTtl = 5 - - minimumChangesToDump = 1024 -- dumpHeader = "mosdns_cache_v1" -+ dumpHeader = "mosdns_cache_v2" - dumpBlockSize = 128 - dumpMaximumBlockLength = 1 << 20 // 1M block. 8kb pre entry. Should be enough. - ) -@@ -379,7 +380,7 @@ func (c *Cache) writeDump(w io.Writer) (int, error) { - return fmt.Errorf("failed to pack msg, %w", err) - } - e := &CachedEntry{ -- Key: string(k), -+ Key: []byte(k), - CacheExpirationTime: cacheExpirationTime.Unix(), - MsgExpirationTime: v.expirationTime.Unix(), - Msg: msg, -diff --git a/plugin/executable/cache/dump.pb.go b/plugin/executable/cache/dump.pb.go -index ba40b95..58a7f15 100644 ---- a/plugin/executable/cache/dump.pb.go -+++ b/plugin/executable/cache/dump.pb.go -@@ -1,7 +1,7 @@ - // Code generated by protoc-gen-go. DO NOT EDIT. - // versions: --// protoc-gen-go v1.28.1 --// protoc v3.21.7 -+// protoc-gen-go v1.31.0 -+// protoc v4.24.3 - // source: plugin/executable/cache/dump.proto - - package cache -@@ -25,7 +25,7 @@ type CachedEntry struct { - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - -- Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` -+ Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Msg []byte `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` - CacheExpirationTime int64 `protobuf:"varint,3,opt,name=cache_expiration_time,json=cacheExpirationTime,proto3" json:"cache_expiration_time,omitempty"` - MsgExpirationTime int64 `protobuf:"varint,4,opt,name=msg_expiration_time,json=msgExpirationTime,proto3" json:"msg_expiration_time,omitempty"` -@@ -64,11 +64,11 @@ func (*CachedEntry) Descriptor() ([]byte, []int) { - return file_plugin_executable_cache_dump_proto_rawDescGZIP(), []int{0} - } - --func (x *CachedEntry) GetKey() string { -+func (x *CachedEntry) GetKey() []byte { - if x != nil { - return x.Key - } -- return "" -+ return nil - } - - func (x *CachedEntry) GetMsg() []byte { -@@ -153,7 +153,7 @@ var file_plugin_executable_cache_dump_proto_rawDesc = []byte{ - 0x62, 0x6c, 0x65, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x64, 0x75, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x63, 0x61, 0x63, 0x68, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x0b, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, -- 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, -+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, - 0x32, 0x0a, 0x15, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, -@@ -185,7 +185,7 @@ func file_plugin_executable_cache_dump_proto_rawDescGZIP() []byte { - } - - var file_plugin_executable_cache_dump_proto_msgTypes = make([]protoimpl.MessageInfo, 2) --var file_plugin_executable_cache_dump_proto_goTypes = []any{ -+var file_plugin_executable_cache_dump_proto_goTypes = []interface{}{ - (*CachedEntry)(nil), // 0: cache.CachedEntry - (*CacheDumpBlock)(nil), // 1: cache.CacheDumpBlock - } -@@ -204,7 +204,7 @@ func file_plugin_executable_cache_dump_proto_init() { - return - } - if !protoimpl.UnsafeEnabled { -- file_plugin_executable_cache_dump_proto_msgTypes[0].Exporter = func(v any, i int) any { -+ file_plugin_executable_cache_dump_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CachedEntry); i { - case 0: - return &v.state -@@ -216,7 +216,7 @@ func file_plugin_executable_cache_dump_proto_init() { - return nil - } - } -- file_plugin_executable_cache_dump_proto_msgTypes[1].Exporter = func(v any, i int) any { -+ file_plugin_executable_cache_dump_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CacheDumpBlock); i { - case 0: - return &v.state -diff --git a/plugin/executable/cache/dump.proto b/plugin/executable/cache/dump.proto -index 756e034..93f1106 100644 ---- a/plugin/executable/cache/dump.proto -+++ b/plugin/executable/cache/dump.proto -@@ -5,7 +5,7 @@ package cache; - option go_package = "plugin/executable/cache"; - - message CachedEntry { -- string key = 1; -+ bytes key = 1; - bytes msg = 2; - int64 cache_expiration_time = 3; - int64 msg_expiration_time = 4; --- -2.34.8 - diff --git a/mosdns/patches/107-add-doq-upstream.patch b/mosdns/patches/107-add-doq-upstream.patch deleted file mode 100644 index c8f94e9..0000000 --- a/mosdns/patches/107-add-doq-upstream.patch +++ /dev/null @@ -1,426 +0,0 @@ -From e30a4d5d8a8e8bd591daa574dd1ff3fd787184d4 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Sun, 17 Sep 2023 19:06:53 +0800 -Subject: [PATCH 08/10] add doq upstream - ---- - pkg/pool/msg_buf.go | 30 ++++ - pkg/pool/msg_buf_test.go | 3 +- - pkg/upstream/doq/upstream.go | 283 +++++++++++++++++++++++++++++++++++ - pkg/upstream/upstream.go | 36 ++++- - 4 files changed, 347 insertions(+), 5 deletions(-) - create mode 100644 pkg/upstream/doq/upstream.go - -diff --git a/pkg/pool/msg_buf.go b/pkg/pool/msg_buf.go -index 980a08b..f132cc2 100644 ---- a/pkg/pool/msg_buf.go -+++ b/pkg/pool/msg_buf.go -@@ -20,6 +20,9 @@ - package pool - - import ( -+ "encoding/binary" -+ "fmt" -+ - "github.com/miekg/dns" - ) - -@@ -40,3 +43,30 @@ func PackBuffer(m *dns.Msg) (wire []byte, buf *[]byte, err error) { - } - return wire, buf, nil - } -+ -+// PackBuffer packs the dns msg m to wire format, with to bytes length header. -+// Callers should release the buf by calling ReleaseBuf. -+func PackTCPBuffer(m *dns.Msg) (buf *[]byte, err error) { -+ b := GetBuf(packBufSize) -+ wire, err := m.PackBuffer((*b)[2:]) -+ if err != nil { -+ ReleaseBuf(b) -+ return nil, err -+ } -+ -+ l := len(wire) -+ if l > dns.MaxMsgSize { -+ ReleaseBuf(b) -+ return nil, fmt.Errorf("dns payload size %d is too large", l) -+ } -+ -+ if &((*b)[0]) != &wire[0] { // reallocated -+ ReleaseBuf(b) -+ b = GetBuf(l + 2) -+ binary.BigEndian.PutUint16((*b)[:2], uint16(l)) -+ copy((*b)[2:], wire) -+ return b, nil -+ } -+ *b = (*b)[:2+l] -+ return b, nil -+} -diff --git a/pkg/pool/msg_buf_test.go b/pkg/pool/msg_buf_test.go -index 02d7348..97d9a76 100644 ---- a/pkg/pool/msg_buf_test.go -+++ b/pkg/pool/msg_buf_test.go -@@ -20,8 +20,9 @@ - package pool - - import ( -- "github.com/miekg/dns" - "testing" -+ -+ "github.com/miekg/dns" - ) - - func TestPackBuffer_No_Allocation(t *testing.T) { -diff --git a/pkg/upstream/doq/upstream.go b/pkg/upstream/doq/upstream.go -new file mode 100644 -index 0000000..43241f4 ---- /dev/null -+++ b/pkg/upstream/doq/upstream.go -@@ -0,0 +1,283 @@ -+/* -+ * Copyright (C) 2020-2022, IrineSistiana -+ * -+ * This file is part of mosdns. -+ * -+ * mosdns is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * mosdns is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+package doq -+ -+import ( -+ "context" -+ "crypto/rand" -+ "crypto/tls" -+ "errors" -+ "net" -+ "sync" -+ "sync/atomic" -+ "time" -+ -+ "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -+ "github.com/IrineSistiana/mosdns/v5/pkg/pool" -+ "github.com/miekg/dns" -+ "github.com/quic-go/quic-go" -+) -+ -+const ( -+ defaultDoQTimeout = time.Second * 5 -+ dialTimeout = time.Second * 3 -+ connectionLostThreshold = time.Second * 5 -+) -+ -+var ( -+ doqAlpn = []string{"doq"} -+) -+ -+type Upstream struct { -+ t *quic.Transport -+ addr string -+ tlsConfig *tls.Config -+ quicConfig *quic.Config -+ -+ cm sync.Mutex -+ lc *lazyConn -+} -+ -+// tlsConfig cannot be nil, it should have Servername or InsecureSkipVerify. -+func NewUpstream(addr string, lc *net.UDPConn, tlsConfig *tls.Config, quicConfig *quic.Config) (*Upstream, error) { -+ srk, err := initSrk() -+ if err != nil { -+ return nil, err -+ } -+ if tlsConfig == nil { -+ return nil, errors.New("nil tls config") -+ } -+ -+ tlsConfig = tlsConfig.Clone() -+ tlsConfig.NextProtos = doqAlpn -+ -+ return &Upstream{ -+ t: &quic.Transport{ -+ Conn: lc, -+ StatelessResetKey: (*quic.StatelessResetKey)(srk), -+ }, -+ addr: addr, -+ tlsConfig: tlsConfig, -+ quicConfig: quicConfig, -+ }, nil -+} -+ -+func initSrk() (*[32]byte, error) { -+ var b [32]byte -+ _, err := rand.Read(b[:]) -+ if err != nil { -+ return nil, err -+ } -+ return &b, nil -+} -+ -+func (u *Upstream) Close() error { -+ return u.t.Close() -+} -+ -+func (u *Upstream) newStream(ctx context.Context) (quic.Stream, *lazyConn, error) { -+ var lc *lazyConn -+ u.cm.Lock() -+ if u.lc == nil { // First dial. -+ u.lc = u.asyncDialConn() -+ } else { -+ select { -+ case <-u.lc.dialFinished: -+ if u.lc.err != nil { // previous dial failed -+ u.lc = u.asyncDialConn() -+ } else { -+ err := u.lc.c.Context().Err() -+ if err != nil { // previous connection is dead or closed -+ u.lc = u.asyncDialConn() -+ } -+ // previous connection looks good -+ } -+ default: -+ // still dialing -+ } -+ } -+ lc = u.lc -+ u.cm.Unlock() -+ -+ select { -+ case <-lc.dialFinished: -+ if lc.c == nil { -+ return nil, nil, lc.err -+ } -+ s, err := lc.c.OpenStream() -+ if err != nil { -+ lc.queryFailedAndCloseIfConnLost(time.Now()) -+ return nil, nil, err -+ } -+ return s, lc, nil -+ case <-ctx.Done(): -+ return nil, nil, ctx.Err() -+ } -+} -+ -+type lazyConn struct { -+ cancelDial func() -+ -+ m sync.Mutex -+ closed bool -+ dialFinished chan struct{} -+ c quic.Connection -+ err error -+ -+ latestRecvMs atomic.Int64 -+} -+ -+func (u *Upstream) asyncDialConn() *lazyConn { -+ ctx, cancel := context.WithTimeout(context.Background(), dialTimeout) -+ lc := &lazyConn{ -+ cancelDial: cancel, -+ dialFinished: make(chan struct{}), -+ } -+ -+ go func() { -+ defer cancel() -+ -+ ua, err := net.ResolveUDPAddr("udp", u.addr) // TODO: Support bootstrap. -+ if err != nil { -+ lc.err = err -+ return -+ } -+ -+ c, err := u.t.Dial(ctx, ua, u.tlsConfig, u.quicConfig) -+ -+ var closeC bool -+ lc.m.Lock() -+ if lc.closed { -+ closeC = true // lc was closed, nothing to do -+ } else { -+ if err != nil { -+ lc.err = err -+ } else { -+ lc.c = c -+ lc.saveLatestRespRecvTime(time.Now()) -+ } -+ close(lc.dialFinished) -+ } -+ lc.m.Unlock() -+ -+ if closeC && c != nil { // lc was closed while dialing. -+ c.CloseWithError(0, "") -+ } -+ }() -+ return lc -+} -+ -+func (lc *lazyConn) close() { -+ lc.m.Lock() -+ defer lc.m.Unlock() -+ -+ if lc.closed { -+ return -+ } -+ lc.closed = true -+ -+ select { -+ case <-lc.dialFinished: -+ if lc.c != nil { -+ lc.c.CloseWithError(0, "") -+ } -+ default: -+ lc.cancelDial() -+ lc.err = net.ErrClosed -+ close(lc.dialFinished) -+ } -+} -+ -+func (lc *lazyConn) saveLatestRespRecvTime(t time.Time) { -+ lc.latestRecvMs.Store(t.UnixMilli()) -+} -+ -+func (lc *lazyConn) latestRespRecvTime() time.Time { -+ return time.UnixMilli(lc.latestRecvMs.Load()) -+} -+ -+func (lc *lazyConn) queryFailedAndCloseIfConnLost(t time.Time) { -+ // No msg received for a quit long time. This connection may be lost. -+ if time.Since(lc.latestRespRecvTime()) > connectionLostThreshold { -+ lc.close() -+ } -+} -+ -+func (u *Upstream) ExchangeContext(ctx context.Context, q *dns.Msg) (*dns.Msg, error) { -+ payload, err := pool.PackTCPBuffer(q) -+ if err != nil { -+ return nil, err -+ } -+ // 4.2.1. DNS Message IDs -+ // When sending queries over a QUIC connection, the DNS Message ID MUST -+ // be set to 0. The stream mapping for DoQ allows for unambiguous -+ // correlation of queries and responses, so the Message ID field is not -+ // required. -+ (*payload)[2], (*payload)[3] = 0, 0 -+ -+ s, lc, err := u.newStream(ctx) -+ if err != nil { -+ return nil, err -+ } -+ -+ type res struct { -+ resp *dns.Msg -+ err error -+ } -+ rc := make(chan res, 1) -+ go func() { -+ defer pool.ReleaseBuf(payload) -+ defer s.Close() -+ r, err := u.exchange(s, *payload) -+ rc <- res{resp: r, err: err} -+ if err != nil { -+ lc.queryFailedAndCloseIfConnLost(time.Now()) -+ } else { -+ lc.saveLatestRespRecvTime(time.Now()) -+ } -+ }() -+ -+ select { -+ case <-ctx.Done(): -+ return nil, context.Cause(ctx) -+ case r := <-rc: -+ resp := r.resp -+ err := r.err -+ if resp != nil { -+ resp.Id = q.Id -+ } -+ return resp, err -+ } -+} -+ -+func (u *Upstream) exchange(s quic.Stream, payload []byte) (*dns.Msg, error) { -+ s.SetDeadline(time.Now().Add(defaultDoQTimeout)) -+ -+ _, err := s.Write(payload) -+ if err != nil { -+ return nil, err -+ } -+ -+ resp, _, err := dnsutils.ReadMsgFromTCP(s) -+ if err != nil { -+ return nil, err -+ } -+ return resp, nil -+} -diff --git a/pkg/upstream/upstream.go b/pkg/upstream/upstream.go -index 8486563..1bc80a2 100644 ---- a/pkg/upstream/upstream.go -+++ b/pkg/upstream/upstream.go -@@ -35,6 +35,7 @@ import ( - "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" - "github.com/IrineSistiana/mosdns/v5/pkg/upstream/bootstrap" - "github.com/IrineSistiana/mosdns/v5/pkg/upstream/doh" -+ "github.com/IrineSistiana/mosdns/v5/pkg/upstream/doq" - "github.com/IrineSistiana/mosdns/v5/pkg/upstream/transport" - "github.com/miekg/dns" - "github.com/quic-go/quic-go" -@@ -181,10 +182,8 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - } - return transport.NewReuseConnTransport(transport.ReuseConnOpts{IOOpts: to}), nil - case "tls": -- var tlsConfig *tls.Config -- if opt.TLSConfig != nil { -- tlsConfig = opt.TLSConfig.Clone() -- } else { -+ tlsConfig := opt.TLSConfig.Clone() -+ if tlsConfig == nil { - tlsConfig = new(tls.Config) - } - if len(tlsConfig.ServerName) == 0 { -@@ -287,6 +286,35 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - Client: &http.Client{Transport: t}, - AddOnCloser: addonCloser, - }, nil -+ case "quic", "doq": -+ tlsConfig := opt.TLSConfig.Clone() -+ if tlsConfig == nil { -+ tlsConfig = new(tls.Config) -+ } -+ if len(tlsConfig.ServerName) == 0 { -+ tlsConfig.ServerName = tryRemovePort(addrURL.Host) -+ } -+ -+ quicConfig := &quic.Config{ -+ TokenStore: quic.NewLRUTokenStore(4, 8), -+ InitialStreamReceiveWindow: 4 * 1024, -+ MaxStreamReceiveWindow: 4 * 1024, -+ InitialConnectionReceiveWindow: 8 * 1024, -+ MaxConnectionReceiveWindow: 64 * 1024, -+ } -+ -+ lc := net.ListenConfig{Control: getSocketControlFunc(socketOpts{so_mark: opt.SoMark, bind_to_device: opt.BindToDevice})} -+ uc, err := lc.ListenPacket(context.Background(), "udp", "") -+ if err != nil { -+ return nil, fmt.Errorf("failed to init udp socket for quic") -+ } -+ -+ dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 853) -+ u, err := doq.NewUpstream(dialAddr, uc.(*net.UDPConn), tlsConfig, quicConfig) -+ if err != nil { -+ return nil, fmt.Errorf("failed to setup doq upstream, %w", err) -+ } -+ return u, nil - default: - return nil, fmt.Errorf("unsupported protocol [%s]", addrURL.Scheme) - } --- -2.34.8 - diff --git a/mosdns/patches/108-workaround-recover-from-0rtt-rejected.patch b/mosdns/patches/108-workaround-recover-from-0rtt-rejected.patch deleted file mode 100644 index 96c93db..0000000 --- a/mosdns/patches/108-workaround-recover-from-0rtt-rejected.patch +++ /dev/null @@ -1,47 +0,0 @@ -From bc22fe05350994d031a1d915b8b1650d23062a52 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Sun, 17 Sep 2023 22:38:11 +0800 -Subject: [PATCH 09/10] workaround: recover from "0rtt rejected" - ---- - pkg/upstream/doq/upstream.go | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/pkg/upstream/doq/upstream.go b/pkg/upstream/doq/upstream.go -index 43241f4..7b2d4e7 100644 ---- a/pkg/upstream/doq/upstream.go -+++ b/pkg/upstream/doq/upstream.go -@@ -39,6 +39,7 @@ const ( - defaultDoQTimeout = time.Second * 5 - dialTimeout = time.Second * 3 - connectionLostThreshold = time.Second * 5 -+ handshakeTimeout = time.Second * 3 - ) - - var ( -@@ -160,7 +161,21 @@ func (u *Upstream) asyncDialConn() *lazyConn { - return - } - -- c, err := u.t.Dial(ctx, ua, u.tlsConfig, u.quicConfig) -+ var c quic.Connection -+ ec, err := u.t.DialEarly(ctx, ua, u.tlsConfig, u.quicConfig) -+ if ec != nil { -+ // This is a workaround to -+ // 1. recover from strange 0rtt rejected err. -+ // 2. avoid NextConnection might block forever. -+ // TODO: Remove this workaround. -+ select { -+ case <-ctx.Done(): -+ err = context.Cause(ctx) -+ ec.CloseWithError(0, "") -+ case <-ec.HandshakeComplete(): -+ c = ec.NextConnection() -+ } -+ } - - var closeC bool - lc.m.Lock() --- -2.34.8 - diff --git a/mosdns/patches/109-upgrade-bytesPool-fixed-714.patch b/mosdns/patches/109-upgrade-bytesPool-fixed-714.patch deleted file mode 100644 index 5f8a5da..0000000 --- a/mosdns/patches/109-upgrade-bytesPool-fixed-714.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 12883ad006dacaabcc4bc5a321e6b69bdfe08db4 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Mon, 18 Sep 2023 19:56:19 +0800 -Subject: [PATCH] upgrade bytesPool, fixed #714 - ---- - go.mod | 2 +- - go.sum | 4 ++++ - pkg/pool/allocator.go | 6 +++--- - 3 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/go.mod b/go.mod -index 2c359e3..f5cb30a 100644 ---- a/go.mod -+++ b/go.mod -@@ -5,7 +5,7 @@ go 1.21 - toolchain go1.21.1 - - require ( -- github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 -+ github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57 - github.com/go-chi/chi/v5 v5.0.10 - github.com/google/nftables v0.1.0 - github.com/kardianos/service v1.2.2 -diff --git a/go.sum b/go.sum -index d4bbaa2..63c84d0 100644 ---- a/go.sum -+++ b/go.sum -@@ -40,6 +40,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 - github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= - github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 h1:5R32cCep3VUDTKf3aurFKfgbvg+RScuBmZsw/DyyXco= - github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918113338-1af74a078e78 h1:Fem1OuBzs4A4kt/MPn09OjZKgphevSoBapSJR/40AzQ= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918113338-1af74a078e78/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57 h1:nfurUSSmVY9sY/mYyoReOA1w2cR2fp2eicL9ojicZhQ= -+github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a h1:GQdh/h0q0ni3L//CXusyk+7QdhBL289vdNaes1WKkHI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ= - github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -diff --git a/pkg/pool/allocator.go b/pkg/pool/allocator.go -index d8ac4ef..eb011ea 100644 ---- a/pkg/pool/allocator.go -+++ b/pkg/pool/allocator.go -@@ -23,8 +23,8 @@ import ( - bytesPool "github.com/IrineSistiana/go-bytes-pool" - ) - --// defaultBufPool is an Allocator that has a maximum capacity. - var ( -- GetBuf = bytesPool.Get -- ReleaseBuf = bytesPool.Release -+ _pool = bytesPool.NewPool(10) // 1Mbyte pool, should be enough. -+ GetBuf = _pool.Get -+ ReleaseBuf = _pool.Release - ) --- -2.34.8 - diff --git a/mosdns/patches/110-fixed-715.patch b/mosdns/patches/110-fixed-715.patch deleted file mode 100644 index 5c6d43c..0000000 --- a/mosdns/patches/110-fixed-715.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 2eaae3d11ea6b6954e820c48c36b9122e3882562 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Tue, 19 Sep 2023 07:59:17 +0800 -Subject: [PATCH] fixed #715 - ---- - pkg/server/udp.go | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index a1e478b..8bb1b85 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -66,14 +66,15 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - if err != nil { - return fmt.Errorf("failed to init oob handler, %w", err) - } -- var ob *[]byte -+ var ob []byte - if oobReader != nil { -- ob = pool.GetBuf(1024) -- defer pool.ReleaseBuf(ob) -+ obp := pool.GetBuf(1024) -+ defer pool.ReleaseBuf(obp) -+ ob = *obp - } - - for { -- n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, *ob) -+ n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, ob) - if err != nil { - return fmt.Errorf("unexpected read err: %w", err) - } -@@ -88,7 +89,7 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - var dstIpFromCm net.IP - if oobReader != nil { - var err error -- dstIpFromCm, err = oobReader((*ob)[:oobn]) -+ dstIpFromCm, err = oobReader(ob[:oobn]) - if err != nil { - s.opts.Logger.Error("failed to get dst address from oob", zap.Error(err)) - } --- -2.34.8 - diff --git a/mosdns/patches/111-pkg-server-decoupling-from-query_context.patch b/mosdns/patches/111-pkg-server-decoupling-from-query_context.patch deleted file mode 100644 index 91e4115..0000000 --- a/mosdns/patches/111-pkg-server-decoupling-from-query_context.patch +++ /dev/null @@ -1,639 +0,0 @@ -From 24c1cd73acc4fb1c9e5fb8a54eff570889ec81a3 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Wed, 20 Sep 2023 09:25:41 +0800 -Subject: [PATCH 1/6] pkg/server: decoupling from query_context - ---- - .../handler.go => http_handler.go} | 68 +++++++++-------- - pkg/server/iface.go | 23 ++++++ - pkg/server/tcp.go | 74 ++++++++----------- - pkg/server/udp.go | 49 ++++-------- - pkg/server/utils.go | 7 ++ - .../entry_handler.go | 31 ++++---- - plugin/server/http_server/http_server.go | 16 ++-- - plugin/server/server_utils/handler.go | 10 ++- - plugin/server/tcp_server/tcp_server.go | 11 ++- - plugin/server/udp_server/udp_server.go | 4 +- - 10 files changed, 144 insertions(+), 149 deletions(-) - rename pkg/server/{http_handler/handler.go => http_handler.go} (75%) - create mode 100644 pkg/server/iface.go - create mode 100644 pkg/server/utils.go - rename pkg/{server/dns_handler => server_handler}/entry_handler.go (77%) - -diff --git a/pkg/server/http_handler/handler.go b/pkg/server/http_handler.go -similarity index 75% -rename from pkg/server/http_handler/handler.go -rename to pkg/server/http_handler.go -index 25f52e1..5fa76b4 100644 ---- a/pkg/server/http_handler/handler.go -+++ b/pkg/server/http_handler.go -@@ -17,69 +17,67 @@ - * along with this program. If not, see . - */ - --package http_handler -+package server - - import ( - "encoding/base64" - "errors" - "fmt" -- "github.com/IrineSistiana/mosdns/v5/mlog" -- "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -- "github.com/IrineSistiana/mosdns/v5/pkg/pool" -- "github.com/IrineSistiana/mosdns/v5/pkg/query_context" -- "github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler" -- "github.com/miekg/dns" -- "go.uber.org/zap" - "io" - "net/http" - "net/netip" - "strings" --) - --type HandlerOpts struct { -- // DNSHandler is required. -- DNSHandler dns_handler.Handler -+ "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -+ "github.com/IrineSistiana/mosdns/v5/pkg/pool" -+ "github.com/miekg/dns" -+ "go.uber.org/zap" -+) - -- // SrcIPHeader specifies the header that contain client source address. -+type HttpHandlerOpts struct { -+ // GetSrcIPFromHeader specifies the header that contain client source address. - // e.g. "X-Forwarded-For". -- SrcIPHeader string -+ GetSrcIPFromHeader string - - // Logger specifies the logger which Handler writes its log to. - // Default is a nop logger. - Logger *zap.Logger - } - --func (opts *HandlerOpts) init() { -- if opts.Logger == nil { -- opts.Logger = mlog.Nop() -- } -- return -+type HttpHandler struct { -+ dnsHandler Handler -+ logger *zap.Logger -+ srcIPHeader string - } - --type Handler struct { -- opts HandlerOpts --} -+var _ http.Handler = (*HttpHandler)(nil) - --func NewHandler(opts HandlerOpts) *Handler { -- opts.init() -- return &Handler{opts: opts} -+func NewHttpHandler(h Handler, opts HttpHandlerOpts) *HttpHandler { -+ hh := new(HttpHandler) -+ hh.dnsHandler = h -+ hh.srcIPHeader = opts.GetSrcIPFromHeader -+ hh.logger = opts.Logger -+ if hh.logger == nil { -+ hh.logger = nopLogger -+ } -+ return hh - } - --func (h *Handler) warnErr(req *http.Request, msg string, err error) { -- h.opts.Logger.Warn(msg, zap.String("from", req.RemoteAddr), zap.String("method", req.Method), zap.String("url", req.RequestURI), zap.Error(err)) -+func (h *HttpHandler) warnErr(req *http.Request, msg string, err error) { -+ h.logger.Warn(msg, zap.String("from", req.RemoteAddr), zap.String("method", req.Method), zap.String("url", req.RequestURI), zap.Error(err)) - } - --func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { -+func (h *HttpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - addrPort, err := netip.ParseAddrPort(req.RemoteAddr) - if err != nil { -- h.opts.Logger.Error("failed to parse request remote addr", zap.String("addr", req.RemoteAddr), zap.Error(err)) -+ h.logger.Error("failed to parse request remote addr", zap.String("addr", req.RemoteAddr), zap.Error(err)) - w.WriteHeader(http.StatusInternalServerError) - return - } - clientAddr := addrPort.Addr() - - // read remote addr from header -- if header := h.opts.SrcIPHeader; len(header) != 0 { -+ if header := h.srcIPHeader; len(header) != 0 { - if xff := req.Header.Get(header); len(xff) != 0 { - addr, err := readClientAddrFromXFF(xff) - if err != nil { -@@ -100,12 +98,12 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - return - } - -- qCtx := query_context.NewContext(q) -- query_context.SetClientAddr(qCtx, &clientAddr) -- if err := h.opts.DNSHandler.ServeDNS(req.Context(), qCtx); err != nil { -- panic(err.Error()) // Force http server to close connection. -+ r, err := h.dnsHandler.Handle(req.Context(), q, QueryMeta{ClientAddr: clientAddr}) -+ if err != nil { -+ h.warnErr(req, "handler err", err) -+ panic(err) // Force http server to close connection. - } -- r := qCtx.R() -+ - b, buf, err := pool.PackBuffer(r) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) -diff --git a/pkg/server/iface.go b/pkg/server/iface.go -new file mode 100644 -index 0000000..2f15be1 ---- /dev/null -+++ b/pkg/server/iface.go -@@ -0,0 +1,23 @@ -+package server -+ -+import ( -+ "context" -+ "net/netip" -+ -+ "github.com/miekg/dns" -+) -+ -+// Handler handles incoming request q and MUST ALWAYS return a response. -+// Handler MUST handle dns errors by itself and return a proper error responses. -+// e.g. Return a SERVFAIL if something goes wrong. -+// If Handle() returns an error, caller considers that the error is associated -+// with the downstream connection and will close the downstream connection -+// immediately. -+type Handler interface { -+ Handle(ctx context.Context, q *dns.Msg, meta QueryMeta) (resp *dns.Msg, err error) -+} -+ -+type QueryMeta struct { -+ ClientAddr netip.Addr // Maybe invalid -+ FromUDP bool -+} -diff --git a/pkg/server/tcp.go b/pkg/server/tcp.go -index 5dc80de..5f479b1 100644 ---- a/pkg/server/tcp.go -+++ b/pkg/server/tcp.go -@@ -22,15 +22,13 @@ package server - import ( - "context" - "fmt" -- "github.com/IrineSistiana/mosdns/v5/mlog" -+ "net" -+ "net/netip" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" - "github.com/IrineSistiana/mosdns/v5/pkg/pool" -- "github.com/IrineSistiana/mosdns/v5/pkg/query_context" -- "github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler" -- "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "go.uber.org/zap" -- "net" -- "time" - ) - - const ( -@@ -38,33 +36,30 @@ const ( - tcpFirstReadTimeout = time.Millisecond * 500 - ) - --type TCPServer struct { -- opts TCPServerOpts --} -- --func NewTCPServer(opts TCPServerOpts) *TCPServer { -- opts.init() -- return &TCPServer{opts: opts} --} -- - type TCPServerOpts struct { -- DNSHandler dns_handler.Handler // Required. -- Logger *zap.Logger -- IdleTimeout time.Duration --} -+ // Nil logger == nop -+ Logger *zap.Logger - --func (opts *TCPServerOpts) init() { -- if opts.Logger == nil { -- opts.Logger = mlog.Nop() -- } -- utils.SetDefaultNum(&opts.IdleTimeout, defaultTCPIdleTimeout) -- return -+ // Default is defaultTCPIdleTimeout. -+ IdleTimeout time.Duration - } - - // ServeTCP starts a server at l. It returns if l had an Accept() error. - // It always returns a non-nil error. --func (s *TCPServer) ServeTCP(l net.Listener) error { -- // handle listener -+func ServeTCP(l net.Listener, h Handler, opts TCPServerOpts) error { -+ logger := opts.Logger -+ if logger == nil { -+ logger = nopLogger -+ } -+ idleTimeout := opts.IdleTimeout -+ if idleTimeout <= 0 { -+ idleTimeout = defaultTCPIdleTimeout -+ } -+ firstReadTimeout := tcpFirstReadTimeout -+ if idleTimeout < firstReadTimeout { -+ firstReadTimeout = idleTimeout -+ } -+ - listenerCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - for { -@@ -79,14 +74,12 @@ func (s *TCPServer) ServeTCP(l net.Listener) error { - defer c.Close() - defer cancelConn() - -- firstReadTimeout := tcpFirstReadTimeout -- idleTimeout := s.opts.IdleTimeout -- if idleTimeout < firstReadTimeout { -- firstReadTimeout = idleTimeout -+ var clientAddr netip.Addr -+ ta, ok := c.RemoteAddr().(*net.TCPAddr) -+ if ok { -+ clientAddr = ta.AddrPort().Addr() - } - -- clientAddr := utils.GetAddrFromAddr(c.RemoteAddr()) -- - firstRead := true - for { - if firstRead { -@@ -102,24 +95,21 @@ func (s *TCPServer) ServeTCP(l net.Listener) error { - - // handle query - go func() { -- qCtx := query_context.NewContext(req) -- query_context.SetClientAddr(qCtx, &clientAddr) -- if err := s.opts.DNSHandler.ServeDNS(tcpConnCtx, qCtx); err != nil { -- s.opts.Logger.Warn("handler err", zap.Error(err)) -- c.Close() -+ r, err := h.Handle(tcpConnCtx, req, QueryMeta{ClientAddr: clientAddr}) -+ if err != nil { -+ logger.Warn("handler err", zap.Error(err)) -+ c.Close() // abort the connection - return - } -- r := qCtx.R() -- - b, buf, err := pool.PackBuffer(r) - if err != nil { -- s.opts.Logger.Error("failed to unpack handler's response", zap.Error(err), zap.Stringer("msg", r)) -+ logger.Error("failed to unpack handler's response", zap.Error(err), zap.Stringer("msg", r)) - return - } - defer pool.ReleaseBuf(buf) - - if _, err := dnsutils.WriteRawMsgToTCP(c, b); err != nil { -- s.opts.Logger.Warn("failed to write response", zap.Stringer("client", c.RemoteAddr()), zap.Error(err)) -+ logger.Warn("failed to write response", zap.Stringer("client", c.RemoteAddr()), zap.Error(err)) - return - } - }() -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index 8bb1b85..247455b 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -24,38 +24,24 @@ import ( - "fmt" - "net" - -- "github.com/IrineSistiana/mosdns/v5/mlog" - "github.com/IrineSistiana/mosdns/v5/pkg/pool" -- "github.com/IrineSistiana/mosdns/v5/pkg/query_context" -- "github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler" - "github.com/miekg/dns" - "go.uber.org/zap" - ) - --type UDPServer struct { -- opts UDPServerOpts --} -- --func NewUDPServer(opts UDPServerOpts) *UDPServer { -- opts.init() -- return &UDPServer{opts: opts} --} -- - type UDPServerOpts struct { -- DNSHandler dns_handler.Handler // Required. -- Logger *zap.Logger --} -- --func (opts *UDPServerOpts) init() { -- if opts.Logger == nil { -- opts.Logger = mlog.Nop() -- } -- return -+ Logger *zap.Logger - } - - // ServeUDP starts a server at c. It returns if c had a read error. - // It always returns a non-nil error. --func (s *UDPServer) ServeUDP(c *net.UDPConn) error { -+// h is required. logger is optional. -+func ServeUDP(c *net.UDPConn, h Handler, opts UDPServerOpts) error { -+ logger := opts.Logger -+ if logger == nil { -+ logger = nopLogger -+ } -+ - listenerCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - -@@ -78,11 +64,10 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - if err != nil { - return fmt.Errorf("unexpected read err: %w", err) - } -- clientAddr := remoteAddr.Addr() - - q := new(dns.Msg) - if err := q.Unpack((*rb)[:n]); err != nil { -- s.opts.Logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", (*rb)[:n]), zap.Stringer("from", remoteAddr)) -+ logger.Warn("invalid msg", zap.Error(err), zap.Binary("msg", (*rb)[:n]), zap.Stringer("from", remoteAddr)) - continue - } - -@@ -91,34 +76,32 @@ func (s *UDPServer) ServeUDP(c *net.UDPConn) error { - var err error - dstIpFromCm, err = oobReader(ob[:oobn]) - if err != nil { -- s.opts.Logger.Error("failed to get dst address from oob", zap.Error(err)) -+ logger.Error("failed to get dst address from oob", zap.Error(err)) - } - } - - // handle query - go func() { -- qCtx := query_context.NewContext(q) -- query_context.SetClientAddr(qCtx, &clientAddr) -- if err := s.opts.DNSHandler.ServeDNS(listenerCtx, qCtx); err != nil { -- s.opts.Logger.Warn("handler err", zap.Error(err)) -+ r, err := h.Handle(listenerCtx, q, QueryMeta{ClientAddr: remoteAddr.Addr(), FromUDP: true}) -+ if err != nil { -+ logger.Warn("handler err", zap.Error(err)) - return - } -- r := qCtx.R() - if r != nil { - r.Truncate(getUDPSize(q)) - b, buf, err := pool.PackBuffer(r) - if err != nil { -- s.opts.Logger.Error("failed to unpack handler's response", zap.Error(err), zap.Stringer("msg", r)) -+ logger.Error("failed to unpack handler's response", zap.Error(err), zap.Stringer("msg", r)) - return - } - defer pool.ReleaseBuf(buf) -- var oob []byte - -+ var oob []byte - if oobWriter != nil && dstIpFromCm != nil { - oob = oobWriter(dstIpFromCm) - } - if _, _, err := c.WriteMsgUDPAddrPort(b, oob, remoteAddr); err != nil { -- s.opts.Logger.Warn("failed to write response", zap.Stringer("client", remoteAddr), zap.Error(err)) -+ logger.Warn("failed to write response", zap.Stringer("client", remoteAddr), zap.Error(err)) - } - } - }() -diff --git a/pkg/server/utils.go b/pkg/server/utils.go -new file mode 100644 -index 0000000..5e1b5c1 ---- /dev/null -+++ b/pkg/server/utils.go -@@ -0,0 +1,7 @@ -+package server -+ -+import "go.uber.org/zap" -+ -+var ( -+ nopLogger = zap.NewNop() -+) -diff --git a/pkg/server/dns_handler/entry_handler.go b/pkg/server_handler/entry_handler.go -similarity index 77% -rename from pkg/server/dns_handler/entry_handler.go -rename to pkg/server_handler/entry_handler.go -index cec4123..121d943 100644 ---- a/pkg/server/dns_handler/entry_handler.go -+++ b/pkg/server_handler/entry_handler.go -@@ -17,17 +17,19 @@ - * along with this program. If not, see . - */ - --package dns_handler -+package server_handler - - import ( - "context" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/mlog" - "github.com/IrineSistiana/mosdns/v5/pkg/query_context" -+ "github.com/IrineSistiana/mosdns/v5/pkg/server" - "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence" - "github.com/miekg/dns" - "go.uber.org/zap" -- "time" - ) - - const ( -@@ -38,18 +40,6 @@ var ( - nopLogger = mlog.Nop() - ) - --// Handler handles dns query. --type Handler interface { -- // ServeDNS handles incoming request qCtx and MUST ALWAYS set a response. -- // Implements must not keep and use qCtx after the ServeDNS returned. -- // ServeDNS should handle dns errors by itself and return a proper error responses -- // for clients. -- // If ServeDNS returns an error, caller considers that the error is associated -- // with the downstream connection and will close the downstream connection -- // immediately. -- ServeDNS(ctx context.Context, qCtx *query_context.Context) error --} -- - type EntryHandlerOpts struct { - // Logger is used for logging. Default is a noop logger. - Logger *zap.Logger -@@ -73,20 +63,26 @@ type EntryHandler struct { - opts EntryHandlerOpts - } - -+var _ server.Handler = (*EntryHandler)(nil) -+ - func NewEntryHandler(opts EntryHandlerOpts) *EntryHandler { - opts.init() - return &EntryHandler{opts: opts} - } - --// ServeDNS implements Handler. -+// ServeDNS implements server.Handler. - // If entry returns an error, a SERVFAIL response will be set. - // If entry returns without a response, a REFUSED response will be set. --func (h *EntryHandler) ServeDNS(ctx context.Context, qCtx *query_context.Context) error { -+func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, qInfo server.QueryMeta) (*dns.Msg, error) { - ddl := time.Now().Add(h.opts.QueryTimeout) - ctx, cancel := context.WithDeadline(ctx, ddl) - defer cancel() - - // exec entry -+ qCtx := query_context.NewContext(q) -+ if qInfo.ClientAddr.IsValid() { -+ query_context.SetClientAddr(qCtx, &qInfo.ClientAddr) -+ } - err := h.opts.Entry.Exec(ctx, qCtx) - respMsg := qCtx.R() - if err != nil { -@@ -106,6 +102,5 @@ func (h *EntryHandler) ServeDNS(ctx context.Context, qCtx *query_context.Context - respMsg.Rcode = dns.RcodeServerFailure - } - respMsg.RecursionAvailable = true -- qCtx.SetResponse(respMsg) -- return nil -+ return respMsg, nil - } -diff --git a/plugin/server/http_server/http_server.go b/plugin/server/http_server/http_server.go -index 8e66b37..daca6db 100644 ---- a/plugin/server/http_server/http_server.go -+++ b/plugin/server/http_server/http_server.go -@@ -21,13 +21,14 @@ package tcp_server - - import ( - "fmt" -+ "net/http" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" -- "github.com/IrineSistiana/mosdns/v5/pkg/server/http_handler" -+ "github.com/IrineSistiana/mosdns/v5/pkg/server" - "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/IrineSistiana/mosdns/v5/plugin/server/server_utils" - "golang.org/x/net/http2" -- "net/http" -- "time" - ) - - const PluginType = "http_server" -@@ -73,12 +74,11 @@ func StartServer(bp *coremain.BP, args *Args) (*HttpServer, error) { - if err != nil { - return nil, fmt.Errorf("failed to init dns handler, %w", err) - } -- hhOpts := http_handler.HandlerOpts{ -- DNSHandler: dh, -- SrcIPHeader: args.SrcIPHeader, -- Logger: bp.L(), -+ hhOpts := server.HttpHandlerOpts{ -+ GetSrcIPFromHeader: args.SrcIPHeader, -+ Logger: bp.L(), - } -- hh := http_handler.NewHandler(hhOpts) -+ hh := server.NewHttpHandler(dh, hhOpts) - mux.Handle(entry.Path, hh) - } - -diff --git a/plugin/server/server_utils/handler.go b/plugin/server/server_utils/handler.go -index 2a20e1a..bbc6eab 100644 ---- a/plugin/server/server_utils/handler.go -+++ b/plugin/server/server_utils/handler.go -@@ -21,21 +21,23 @@ package server_utils - - import ( - "fmt" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" -- "github.com/IrineSistiana/mosdns/v5/pkg/server/dns_handler" -+ "github.com/IrineSistiana/mosdns/v5/pkg/server" -+ "github.com/IrineSistiana/mosdns/v5/pkg/server_handler" - "github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence" - ) - --func NewHandler(bp *coremain.BP, entry string) (dns_handler.Handler, error) { -+func NewHandler(bp *coremain.BP, entry string) (server.Handler, error) { - p := bp.M().GetPlugin(entry) - exec := sequence.ToExecutable(p) - if exec == nil { - return nil, fmt.Errorf("cannot find executable entry by tag %s", entry) - } - -- handlerOpts := dns_handler.EntryHandlerOpts{ -+ handlerOpts := server_handler.EntryHandlerOpts{ - Logger: bp.L(), - Entry: exec, - } -- return dns_handler.NewEntryHandler(handlerOpts), nil -+ return server_handler.NewEntryHandler(handlerOpts), nil - } -diff --git a/plugin/server/tcp_server/tcp_server.go b/plugin/server/tcp_server/tcp_server.go -index 5aca0f5..f69c667 100644 ---- a/plugin/server/tcp_server/tcp_server.go -+++ b/plugin/server/tcp_server/tcp_server.go -@@ -22,12 +22,13 @@ package tcp_server - import ( - "crypto/tls" - "fmt" -+ "net" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" - "github.com/IrineSistiana/mosdns/v5/pkg/server" - "github.com/IrineSistiana/mosdns/v5/pkg/utils" - "github.com/IrineSistiana/mosdns/v5/plugin/server/server_utils" -- "net" -- "time" - ) - - const PluginType = "tcp_server" -@@ -69,9 +70,6 @@ func StartServer(bp *coremain.BP, args *Args) (*TcpServer, error) { - return nil, fmt.Errorf("failed to init dns handler, %w", err) - } - -- serverOpts := server.TCPServerOpts{Logger: bp.L(), DNSHandler: dh, IdleTimeout: time.Duration(args.IdleTimeout) * time.Second} -- s := server.NewTCPServer(serverOpts) -- - // Init tls - var tc *tls.Config - if len(args.Key)+len(args.Cert) > 0 { -@@ -91,7 +89,8 @@ func StartServer(bp *coremain.BP, args *Args) (*TcpServer, error) { - - go func() { - defer l.Close() -- err := s.ServeTCP(l) -+ serverOpts := server.TCPServerOpts{Logger: bp.L(), IdleTimeout: time.Duration(args.IdleTimeout) * time.Second} -+ err := server.ServeTCP(l, dh, serverOpts) - bp.M().GetSafeClose().SendCloseSignal(err) - }() - return &TcpServer{ -diff --git a/plugin/server/udp_server/udp_server.go b/plugin/server/udp_server/udp_server.go -index 293f720..988f312 100644 ---- a/plugin/server/udp_server/udp_server.go -+++ b/plugin/server/udp_server/udp_server.go -@@ -64,15 +64,13 @@ func StartServer(bp *coremain.BP, args *Args) (*UdpServer, error) { - return nil, fmt.Errorf("failed to init dns handler, %w", err) - } - -- serverOpts := server.UDPServerOpts{Logger: bp.L(), DNSHandler: dh} -- s := server.NewUDPServer(serverOpts) - c, err := net.ListenPacket("udp", args.Listen) - if err != nil { - return nil, fmt.Errorf("failed to create socket, %w", err) - } - go func() { - defer c.Close() -- err := s.ServeUDP(c.(*net.UDPConn)) -+ err := server.ServeUDP(c.(*net.UDPConn), dh, server.UDPServerOpts{Logger: bp.L()}) - bp.M().GetSafeClose().SendCloseSignal(err) - }() - return &UdpServer{ --- -2.34.8 - diff --git a/mosdns/patches/112-server-don-t-exit-udp-server-on-tempory-read-err.patch b/mosdns/patches/112-server-don-t-exit-udp-server-on-tempory-read-err.patch deleted file mode 100644 index ba8bf0d..0000000 --- a/mosdns/patches/112-server-don-t-exit-udp-server-on-tempory-read-err.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 61c1586082d21ad793447c3c4510230b492ffbc0 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Wed, 20 Sep 2023 09:31:39 +0800 -Subject: [PATCH 2/6] server: don't exit udp server on tempory read err - ---- - pkg/server/udp.go | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/pkg/server/udp.go b/pkg/server/udp.go -index 247455b..4dc1087 100644 ---- a/pkg/server/udp.go -+++ b/pkg/server/udp.go -@@ -62,7 +62,13 @@ func ServeUDP(c *net.UDPConn, h Handler, opts UDPServerOpts) error { - for { - n, oobn, _, remoteAddr, err := c.ReadMsgUDPAddrPort(*rb, ob) - if err != nil { -- return fmt.Errorf("unexpected read err: %w", err) -+ if n == 0 { -+ // err with zero read. Most likely becasue c was closed. -+ return fmt.Errorf("unexpected read err: %w", err) -+ } -+ // err with some read. Tempory err. -+ logger.Warn("read err", zap.Error(err)) -+ continue - } - - q := new(dns.Msg) --- -2.34.8 - diff --git a/mosdns/patches/113-pool-fixed-bytes-pool-size-was-1k.patch b/mosdns/patches/113-pool-fixed-bytes-pool-size-was-1k.patch deleted file mode 100644 index e06d600..0000000 --- a/mosdns/patches/113-pool-fixed-bytes-pool-size-was-1k.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c19d24ab47674c2a82591c9e16fb450df7882465 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Thu, 21 Sep 2023 08:57:07 +0800 -Subject: [PATCH 3/6] pool: fixed bytes pool size was 1k - ---- - pkg/pool/allocator.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkg/pool/allocator.go b/pkg/pool/allocator.go -index eb011ea..84b1110 100644 ---- a/pkg/pool/allocator.go -+++ b/pkg/pool/allocator.go -@@ -24,7 +24,7 @@ import ( - ) - - var ( -- _pool = bytesPool.NewPool(10) // 1Mbyte pool, should be enough. -+ _pool = bytesPool.NewPool(20) // 1Mbyte pool, should be enough. - GetBuf = _pool.Get - ReleaseBuf = _pool.Release - ) --- -2.34.8 - diff --git a/mosdns/patches/114-pool-fixed-PackTCPBuffer-always-re-allocate.patch b/mosdns/patches/114-pool-fixed-PackTCPBuffer-always-re-allocate.patch deleted file mode 100644 index c619b7e..0000000 --- a/mosdns/patches/114-pool-fixed-PackTCPBuffer-always-re-allocate.patch +++ /dev/null @@ -1,32 +0,0 @@ -From bedebc75e1f88d02e737203b09041c39094d5777 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Thu, 21 Sep 2023 11:04:03 +0800 -Subject: [PATCH 4/6] pool: fixed PackTCPBuffer always re-allocate - ---- - pkg/pool/msg_buf.go | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/pkg/pool/msg_buf.go b/pkg/pool/msg_buf.go -index f132cc2..11faf7d 100644 ---- a/pkg/pool/msg_buf.go -+++ b/pkg/pool/msg_buf.go -@@ -60,13 +60,14 @@ func PackTCPBuffer(m *dns.Msg) (buf *[]byte, err error) { - return nil, fmt.Errorf("dns payload size %d is too large", l) - } - -- if &((*b)[0]) != &wire[0] { // reallocated -+ if &((*b)[2]) != &wire[0] { // reallocated - ReleaseBuf(b) - b = GetBuf(l + 2) - binary.BigEndian.PutUint16((*b)[:2], uint16(l)) - copy((*b)[2:], wire) - return b, nil - } -+ binary.BigEndian.PutUint16((*b)[:2], uint16(l)) - *b = (*b)[:2+l] - return b, nil - } --- -2.34.8 - diff --git a/mosdns/patches/115-dnsutils-let-WriteMsgToTCP-use-PackTCPBuffer.patch b/mosdns/patches/115-dnsutils-let-WriteMsgToTCP-use-PackTCPBuffer.patch deleted file mode 100644 index 3bd7c4e..0000000 --- a/mosdns/patches/115-dnsutils-let-WriteMsgToTCP-use-PackTCPBuffer.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f0005ccc3a27dcbcc2266c550ffb7acf688523f0 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Thu, 21 Sep 2023 11:04:35 +0800 -Subject: [PATCH 5/6] dnsutils: let WriteMsgToTCP use PackTCPBuffer - ---- - pkg/dnsutils/net_io.go | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkg/dnsutils/net_io.go b/pkg/dnsutils/net_io.go -index 8fc769b..f165446 100644 ---- a/pkg/dnsutils/net_io.go -+++ b/pkg/dnsutils/net_io.go -@@ -78,12 +78,12 @@ func ReadMsgFromTCP(c io.Reader) (*dns.Msg, int, error) { - // WriteMsgToTCP packs and writes m to c in RFC 1035 format. - // n represents how many bytes are written to c. - func WriteMsgToTCP(c io.Writer, m *dns.Msg) (n int, err error) { -- mRaw, buf, err := pool.PackBuffer(m) -+ buf, err := pool.PackTCPBuffer(m) - if err != nil { - return 0, err - } - defer pool.ReleaseBuf(buf) -- return WriteRawMsgToTCP(c, mRaw) -+ return c.Write(*buf) - } - - // WriteRawMsgToTCP See WriteMsgToTCP --- -2.34.8 - diff --git a/mosdns/patches/116-upstream-switch-to-self-implement-bootstrap.patch b/mosdns/patches/116-upstream-switch-to-self-implement-bootstrap.patch deleted file mode 100644 index c51e3f5..0000000 --- a/mosdns/patches/116-upstream-switch-to-self-implement-bootstrap.patch +++ /dev/null @@ -1,1540 +0,0 @@ -From 5b96077d2a44d085a8ae44b1b368808184dea64b Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Thu, 21 Sep 2023 11:52:20 +0800 -Subject: [PATCH 6/6] upstream: switch to self implement bootstrap - -refine code structure ---- - pkg/upstream/bootstrap/bootstrap.go | 324 ++++++++++++---------- - pkg/upstream/bootstrap/bootstrap_test.go | 38 --- - pkg/upstream/doh/upstream.go | 24 +- - pkg/upstream/doq/upstream.go | 66 +---- - pkg/upstream/event_stat.go | 2 +- - pkg/upstream/transport/dns_conn.go | 3 +- - pkg/upstream/transport/dns_conn_test.go | 7 +- - pkg/upstream/transport/pipeline.go | 3 +- - pkg/upstream/transport/pipeline_test.go | 3 +- - pkg/upstream/transport/reuse.go | 3 +- - pkg/upstream/transport/reuse_test.go | 3 +- - pkg/upstream/transport/transport.go | 3 +- - pkg/upstream/transport/utils.go | 46 ++-- - pkg/upstream/upstream.go | 337 ++++++++++++++++++----- - pkg/upstream/upstream_test.go | 8 +- - pkg/upstream/utils.go | 72 ++++- - pkg/upstream/utils_unix.go | 3 +- - plugin/executable/forward/forward.go | 9 +- - 18 files changed, 586 insertions(+), 368 deletions(-) - delete mode 100644 pkg/upstream/bootstrap/bootstrap_test.go - -diff --git a/pkg/upstream/bootstrap/bootstrap.go b/pkg/upstream/bootstrap/bootstrap.go -index b831757..2cd8ef9 100644 ---- a/pkg/upstream/bootstrap/bootstrap.go -+++ b/pkg/upstream/bootstrap/bootstrap.go -@@ -21,184 +21,226 @@ package bootstrap - - import ( - "context" -- "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -- "github.com/miekg/dns" -+ "errors" -+ "fmt" - "net" -- "strings" -+ "net/netip" - "sync" -+ "sync/atomic" - "time" -+ -+ "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -+ "github.com/miekg/dns" -+ "go.uber.org/zap" - ) - --// NewBootstrap returns a customized *net.Resolver which can be used as a Bootstrap for a --// certain domain. Its Dial func is modified to dial s through udp. --// It also has a small built-in cache. --// s SHOULD be a literal IP address and the port SHOULD also be literal. --// Port can be omitted. In this case, the default port is :53. --// e.g. NewBootstrap("8.8.8.8"), NewBootstrap("127.0.0.1:5353"). --// If s is empty, NewBootstrap returns nil. (A nil *net.Resolver is valid in net.Dialer.) --// Note that not all platform support a customized *net.Resolver. It also depends on the --// version of go runtime. --// See the package docs from the net package for more info. --func NewBootstrap(s string) *net.Resolver { -- if len(s) == 0 { -- return nil -- } -- // Add port. -- _, _, err := net.SplitHostPort(s) -- if err != nil { // no port, add it. -- s = net.JoinHostPort(strings.Trim(s, "[]"), "53") -- } -+const ( -+ minimumUpdateInterval = time.Minute * 5 -+ retryInterval = time.Second * 2 -+ queryTimeout = time.Second * 5 -+) - -- bs := newBootstrap(s) -+var ( -+ errNoAddrInResp = errors.New("resp does not have ip address") -+) - -- return &net.Resolver{ -- PreferGo: true, -- StrictErrors: false, -- Dial: bs.dial, -+func New( -+ host string, -+ port uint16, -+ bootstrapServer netip.AddrPort, -+ bootstrapVer int, // 0,4,6 -+ logger *zap.Logger, // not nil -+) (*Bootstrap, error) { -+ dp := new(Bootstrap) -+ dp.fqdn = dns.Fqdn(host) -+ dp.port = port -+ if !bootstrapServer.IsValid() { -+ return nil, errors.New("invalid bootstrap server address") -+ } -+ dp.bootstrap = net.UDPAddrFromAddrPort(bootstrapServer) -+ qt, ok := bootstrapVer2Qt(bootstrapVer) -+ if !ok { -+ return nil, fmt.Errorf("invalid bootstrap version %d", bootstrapVer) - } --} -+ dp.qt = qt -+ dp.logger = logger - --type bootstrap struct { -- upstream string -- cache *cache -+ dp.readyNotify = make(chan struct{}) -+ return dp, nil - } - --func newBootstrap(upstream string) *bootstrap { -- return &bootstrap{ -- upstream: upstream, -- cache: newCache(0), -- } --} -+type Bootstrap struct { -+ fqdn string -+ port uint16 -+ bootstrap *net.UDPAddr -+ qt uint16 // dns.TypeA or dns.TypeAAAA -+ logger *zap.Logger // not nil - --func (b *bootstrap) dial(_ context.Context, _, _ string) (net.Conn, error) { -- c1, c2 := net.Pipe() -- go func() { -- _ = b.handlePipe(c2) -- _ = c2.Close() -- }() -- return c1, nil --} -+ updating atomic.Bool -+ nextUpdate time.Time - --func (b *bootstrap) handlePipe(c net.Conn) error { -- q, _, err := dnsutils.ReadMsgFromTCP(c) -- if err != nil { -- return err -- } -- -- var resp *dns.Msg -- if len(q.Question) == 1 { -- k := q.Question[0] -- m := b.cache.lookup(k) -- if m != nil { -- resp = m.Copy() -- resp.Id = q.Id -- } -- } -+ readyNotify chan struct{} -+ m sync.Mutex -+ ready bool -+ addrStr string -+} - -- if resp == nil { -- d := net.Dialer{} -- ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) -- defer cancel() -- upstreamConn, err := d.DialContext(ctx, "udp", b.upstream) -- if err != nil { -- return err -- } -- defer upstreamConn.Close() -- _ = upstreamConn.SetDeadline(time.Now().Add(time.Second * 3)) -- if _, err := dnsutils.WriteMsgToUDP(upstreamConn, q); err != nil { -- return err -- } -- m, _, err := dnsutils.ReadMsgFromUDP(upstreamConn, 1500) -- if err != nil { -- return err -- } -- resp = m -- } -+func (sp *Bootstrap) GetAddrPortStr(ctx context.Context) (string, error) { -+ sp.tryUpdate() - -- if resp.Rcode == dns.RcodeSuccess && hasIP(resp) { -- if len(resp.Question) == 1 { -- k := resp.Question[0] -- ttl := time.Duration(dnsutils.GetMinimalTTL(resp)) * time.Second -- b.cache.store(k, resp, ttl) -- } -+ select { -+ case <-ctx.Done(): -+ return "", ctx.Err() -+ case <-sp.readyNotify: - } - -- _, err = dnsutils.WriteMsgToTCP(c, resp) -- return err -+ sp.m.Lock() -+ addr := sp.addrStr -+ sp.m.Unlock() -+ return addr, nil - } - --func hasIP(m *dns.Msg) bool { -- for _, rr := range m.Answer { -- switch rr.Header().Rrtype { -- case dns.TypeA, dns.TypeAAAA: -- return true -+func (sp *Bootstrap) tryUpdate() { -+ if sp.updating.CompareAndSwap(false, true) { -+ if time.Now().After(sp.nextUpdate) { -+ go func() { -+ defer sp.updating.Store(false) -+ ctx, cancel := context.WithTimeout(context.Background(), queryTimeout) -+ defer cancel() -+ start := time.Now() -+ addr, ttl, err := sp.updateAddr(ctx) -+ if err != nil { -+ sp.logger.Warn("failed to update bootstrap addr", zap.String("fqdn", sp.fqdn), zap.Error(err)) -+ sp.nextUpdate = time.Now().Add(retryInterval) -+ } else { -+ updateInterval := time.Second * time.Duration(ttl) -+ if updateInterval < minimumUpdateInterval { -+ updateInterval = minimumUpdateInterval -+ } -+ sp.logger.Info( -+ "bootstrap addr updated", -+ zap.String("fqdn", sp.fqdn), -+ zap.Stringer("addr", addr), -+ zap.Duration("ttl", updateInterval), -+ zap.Duration("elapse", time.Since(start)), -+ ) -+ sp.nextUpdate = time.Now().Add(updateInterval) -+ } -+ }() -+ } else { -+ sp.updating.Store(false) - } - } -- return false - } - --type cache struct { -- l int -+func (sp *Bootstrap) updateAddr(ctx context.Context) (netip.Addr, uint32, error) { -+ addr, ttl, err := sp.resolve(ctx, sp.qt) -+ if err != nil { -+ return netip.Addr{}, 0, err -+ } - -- m sync.Mutex -- c map[key]*elem -+ addrPort := netip.AddrPortFrom(addr, sp.port).String() -+ sp.m.Lock() -+ sp.addrStr = addrPort -+ if !sp.ready { -+ sp.ready = true -+ close(sp.readyNotify) -+ } -+ sp.m.Unlock() -+ return addr, ttl, nil - } - --type elem struct { -- m *dns.Msg -- expirationTime time.Time --} -+func (sp *Bootstrap) resolve(ctx context.Context, qt uint16) (netip.Addr, uint32, error) { -+ const edns0UdpSize = 1200 - --type key = dns.Question -+ q := new(dns.Msg) -+ q.SetQuestion(sp.fqdn, qt) -+ q.SetEdns0(edns0UdpSize, false) - --func newCache(size int) *cache { -- const defaultSize = 8 -- if size <= 0 { -- size = defaultSize -- } -- return &cache{ -- l: size, -- c: make(map[key]*elem), -+ c, err := net.DialUDP("udp", nil, sp.bootstrap) -+ if err != nil { -+ return netip.Addr{}, 0, err - } --} -+ defer c.Close() - --// lookup returns a cached msg. Note: the msg must not be modified. --func (c *cache) lookup(k key) *dns.Msg { -- now := time.Now() -- c.m.Lock() -- defer c.m.Unlock() -- e, ok := c.c[k] -- if !ok { -- return nil -- } -- if e.expirationTime.Before(now) { -- delete(c.c, k) -- return nil -+ writeErrC := make(chan error, 1) -+ type res struct { -+ resp *dns.Msg -+ err error - } -- return e.m --} -+ readResC := make(chan res, 1) - --// store stores a msg to cache. The caller MUST NOT modify m anymore. --func (c *cache) store(k key, m *dns.Msg, ttl time.Duration) { -- if ttl <= 0 { -- return -- } -- expirationTime := time.Now().Add(ttl) -+ cancelWrite := make(chan struct{}) -+ defer close(cancelWrite) -+ go func() { -+ if _, err := dnsutils.WriteMsgToUDP(c, q); err != nil { -+ writeErrC <- err -+ return -+ } - -- c.m.Lock() -- defer c.m.Unlock() -+ retryTicker := time.NewTicker(time.Second) -+ defer retryTicker.Stop() -+ for { -+ select { -+ case <-cancelWrite: -+ return -+ case <-retryTicker.C: -+ if _, err := dnsutils.WriteMsgToUDP(c, q); err != nil { -+ writeErrC <- err -+ return -+ } -+ } -+ } -+ }() -+ -+ go func() { -+ m, _, err := dnsutils.ReadMsgFromUDP(c, edns0UdpSize) -+ readResC <- res{resp: m, err: err} -+ }() - -- if len(c.c)+1 > c.l { -- for k := range c.c { -- if len(c.c)+1 <= c.l { -- break -+ select { -+ case <-ctx.Done(): -+ return netip.Addr{}, 0, ctx.Err() -+ case err := <-writeErrC: -+ return netip.Addr{}, 0, fmt.Errorf("failed to write query, %w", err) -+ case r := <-readResC: -+ resp := r.resp -+ err := r.err -+ if err != nil { -+ return netip.Addr{}, 0, fmt.Errorf("failed to read resp, %w", err) -+ } -+ -+ for _, v := range resp.Answer { -+ var ip net.IP -+ var ttl uint32 -+ switch rr := v.(type) { -+ case *dns.A: -+ ip = rr.A -+ ttl = rr.Hdr.Ttl -+ case *dns.AAAA: -+ ip = rr.AAAA -+ ttl = rr.Hdr.Ttl -+ default: -+ continue -+ } -+ addr, ok := netip.AddrFromSlice(ip) -+ if ok { -+ return addr, ttl, nil - } -- delete(c.c, k) - } -+ -+ // No ip addr in resp. -+ return netip.Addr{}, 0, errNoAddrInResp - } -+} - -- c.c[k] = &elem{ -- m: m, -- expirationTime: expirationTime, -+func bootstrapVer2Qt(ver int) (uint16, bool) { -+ switch ver { -+ case 0, 4: -+ return dns.TypeA, true -+ case 6: -+ return dns.TypeAAAA, true -+ default: -+ return 0, false - } - } -diff --git a/pkg/upstream/bootstrap/bootstrap_test.go b/pkg/upstream/bootstrap/bootstrap_test.go -deleted file mode 100644 -index 93f14ff..0000000 ---- a/pkg/upstream/bootstrap/bootstrap_test.go -+++ /dev/null -@@ -1,38 +0,0 @@ --/* -- * Copyright (C) 2020-2022, IrineSistiana -- * -- * This file is part of mosdns. -- * -- * mosdns is free software: you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation, either version 3 of the License, or -- * (at your option) any later version. -- * -- * mosdns is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- */ -- --package bootstrap -- --import ( -- "context" -- "os" -- "testing" --) -- --func Test_Bootstrap(t *testing.T) { -- if os.Getenv("TEST_BOOTSTRAP") == "" { -- t.SkipNow() -- } -- -- r := NewBootstrap("8.8.8.8") -- _, err := r.LookupIP(context.Background(), "ip", "google.com") -- if err != nil { -- t.Fatal(err) -- } --} -diff --git a/pkg/upstream/doh/upstream.go b/pkg/upstream/doh/upstream.go -index addf5b7..abc124b 100644 ---- a/pkg/upstream/doh/upstream.go -+++ b/pkg/upstream/doh/upstream.go -@@ -23,13 +23,14 @@ import ( - "context" - "encoding/base64" - "fmt" -- "github.com/IrineSistiana/mosdns/v5/pkg/pool" -- "github.com/IrineSistiana/mosdns/v5/pkg/utils" -- "github.com/miekg/dns" - "io" - "net/http" - "strings" - "time" -+ -+ "github.com/IrineSistiana/mosdns/v5/pkg/pool" -+ "github.com/IrineSistiana/mosdns/v5/pkg/utils" -+ "github.com/miekg/dns" - ) - - const ( -@@ -42,21 +43,10 @@ type Upstream struct { - EndPoint string - // Client is a http.Client that sends http requests. - Client *http.Client -- -- // AddOnCloser will be closed when Upstream is closed. -- AddOnCloser io.Closer - } - --func (u *Upstream) CloseIdleConnections() { -- u.Client.CloseIdleConnections() --} -- --func (u *Upstream) Close() error { -- u.Client.CloseIdleConnections() -- if u.AddOnCloser != nil { -- u.AddOnCloser.Close() -- } -- return nil -+func NewUpstream(endPoint string, client *http.Client) *Upstream { -+ return &Upstream{EndPoint: endPoint, Client: client} - } - - var ( -@@ -127,7 +117,7 @@ func (u *Upstream) ExchangeContext(ctx context.Context, q *dns.Msg) (*dns.Msg, e - func (u *Upstream) exchange(ctx context.Context, url string) (*dns.Msg, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { -- return nil, fmt.Errorf("interal err: NewRequestWithContext: %w", err) -+ return nil, fmt.Errorf("internal err: NewRequestWithContext: %w", err) - } - - req.Header["Accept"] = []string{"application/dns-message"} -diff --git a/pkg/upstream/doq/upstream.go b/pkg/upstream/doq/upstream.go -index 7b2d4e7..23d7f1c 100644 ---- a/pkg/upstream/doq/upstream.go -+++ b/pkg/upstream/doq/upstream.go -@@ -22,8 +22,6 @@ package doq - import ( - "context" - "crypto/rand" -- "crypto/tls" -- "errors" - "net" - "sync" - "sync/atomic" -@@ -39,48 +37,27 @@ const ( - defaultDoQTimeout = time.Second * 5 - dialTimeout = time.Second * 3 - connectionLostThreshold = time.Second * 5 -- handshakeTimeout = time.Second * 3 - ) - - var ( -- doqAlpn = []string{"doq"} -+ DoqAlpn = []string{"doq"} - ) - - type Upstream struct { -- t *quic.Transport -- addr string -- tlsConfig *tls.Config -- quicConfig *quic.Config -+ dialer func(ctx context.Context) (quic.Connection, error) - - cm sync.Mutex - lc *lazyConn - } - --// tlsConfig cannot be nil, it should have Servername or InsecureSkipVerify. --func NewUpstream(addr string, lc *net.UDPConn, tlsConfig *tls.Config, quicConfig *quic.Config) (*Upstream, error) { -- srk, err := initSrk() -- if err != nil { -- return nil, err -- } -- if tlsConfig == nil { -- return nil, errors.New("nil tls config") -- } -- -- tlsConfig = tlsConfig.Clone() -- tlsConfig.NextProtos = doqAlpn -- -+func NewUpstream(dialer func(ctx context.Context) (quic.Connection, error)) *Upstream { - return &Upstream{ -- t: &quic.Transport{ -- Conn: lc, -- StatelessResetKey: (*quic.StatelessResetKey)(srk), -- }, -- addr: addr, -- tlsConfig: tlsConfig, -- quicConfig: quicConfig, -- }, nil -+ dialer: dialer, -+ } - } - --func initSrk() (*[32]byte, error) { -+// A helper func to init quic stateless reset key. -+func InitSrk() (*[32]byte, error) { - var b [32]byte - _, err := rand.Read(b[:]) - if err != nil { -@@ -89,10 +66,6 @@ func initSrk() (*[32]byte, error) { - return &b, nil - } - --func (u *Upstream) Close() error { -- return u.t.Close() --} -- - func (u *Upstream) newStream(ctx context.Context) (quic.Stream, *lazyConn, error) { - var lc *lazyConn - u.cm.Lock() -@@ -154,31 +127,10 @@ func (u *Upstream) asyncDialConn() *lazyConn { - - go func() { - defer cancel() -+ c, err := u.dialer(ctx) - -- ua, err := net.ResolveUDPAddr("udp", u.addr) // TODO: Support bootstrap. -- if err != nil { -- lc.err = err -- return -- } -- -- var c quic.Connection -- ec, err := u.t.DialEarly(ctx, ua, u.tlsConfig, u.quicConfig) -- if ec != nil { -- // This is a workaround to -- // 1. recover from strange 0rtt rejected err. -- // 2. avoid NextConnection might block forever. -- // TODO: Remove this workaround. -- select { -- case <-ctx.Done(): -- err = context.Cause(ctx) -- ec.CloseWithError(0, "") -- case <-ec.HandshakeComplete(): -- c = ec.NextConnection() -- } -- } -- -- var closeC bool - lc.m.Lock() -+ var closeC bool - if lc.closed { - closeC = true // lc was closed, nothing to do - } else { -diff --git a/pkg/upstream/event_stat.go b/pkg/upstream/event_stat.go -index cfb40c5..6b7b803 100644 ---- a/pkg/upstream/event_stat.go -+++ b/pkg/upstream/event_stat.go -@@ -37,7 +37,7 @@ type EventObserver interface { - - type nopEO struct{} - --func (n nopEO) OnEvent(_ Event) { return } -+func (n nopEO) OnEvent(_ Event) {} - - type connWrapper struct { - net.Conn -diff --git a/pkg/upstream/transport/dns_conn.go b/pkg/upstream/transport/dns_conn.go -index 1c81a92..6df458e 100644 ---- a/pkg/upstream/transport/dns_conn.go -+++ b/pkg/upstream/transport/dns_conn.go -@@ -22,10 +22,11 @@ package transport - import ( - "context" - "fmt" -- "github.com/miekg/dns" - "io" - "sync" - "sync/atomic" -+ -+ "github.com/miekg/dns" - ) - - // dnsConn is a low-level connection for dns. -diff --git a/pkg/upstream/transport/dns_conn_test.go b/pkg/upstream/transport/dns_conn_test.go -index c677797..6e4eb27 100644 ---- a/pkg/upstream/transport/dns_conn_test.go -+++ b/pkg/upstream/transport/dns_conn_test.go -@@ -22,9 +22,6 @@ package transport - import ( - "context" - "errors" -- "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -- "github.com/IrineSistiana/mosdns/v5/pkg/pool" -- "github.com/miekg/dns" - "io" - "math/rand" - "net" -@@ -32,6 +29,10 @@ import ( - "sync" - "testing" - "time" -+ -+ "github.com/IrineSistiana/mosdns/v5/pkg/dnsutils" -+ "github.com/IrineSistiana/mosdns/v5/pkg/pool" -+ "github.com/miekg/dns" - ) - - var ( -diff --git a/pkg/upstream/transport/pipeline.go b/pkg/upstream/transport/pipeline.go -index e4bc39e..10c3d23 100644 ---- a/pkg/upstream/transport/pipeline.go -+++ b/pkg/upstream/transport/pipeline.go -@@ -21,10 +21,11 @@ package transport - - import ( - "context" -- "github.com/miekg/dns" - "math/rand" - "sync" - "time" -+ -+ "github.com/miekg/dns" - ) - - // PipelineTransport will pipeline queries as RFC 7766 6.2.1.1 suggested. -diff --git a/pkg/upstream/transport/pipeline_test.go b/pkg/upstream/transport/pipeline_test.go -index 5fcc0ae..653d779 100644 ---- a/pkg/upstream/transport/pipeline_test.go -+++ b/pkg/upstream/transport/pipeline_test.go -@@ -21,10 +21,11 @@ package transport - - import ( - "context" -- "github.com/miekg/dns" - "sync" - "testing" - "time" -+ -+ "github.com/miekg/dns" - ) - - // Leak and race tests. -diff --git a/pkg/upstream/transport/reuse.go b/pkg/upstream/transport/reuse.go -index c005dc0..5489833 100644 ---- a/pkg/upstream/transport/reuse.go -+++ b/pkg/upstream/transport/reuse.go -@@ -21,8 +21,9 @@ package transport - - import ( - "context" -- "github.com/miekg/dns" - "sync" -+ -+ "github.com/miekg/dns" - ) - - type ReuseConnTransport struct { -diff --git a/pkg/upstream/transport/reuse_test.go b/pkg/upstream/transport/reuse_test.go -index 3b45961..ac68142 100644 ---- a/pkg/upstream/transport/reuse_test.go -+++ b/pkg/upstream/transport/reuse_test.go -@@ -21,10 +21,11 @@ package transport - - import ( - "context" -- "github.com/miekg/dns" - "sync" - "testing" - "time" -+ -+ "github.com/miekg/dns" - ) - - // Leak and race tests. -diff --git a/pkg/upstream/transport/transport.go b/pkg/upstream/transport/transport.go -index 4542d65..d393600 100644 ---- a/pkg/upstream/transport/transport.go -+++ b/pkg/upstream/transport/transport.go -@@ -22,9 +22,10 @@ package transport - import ( - "context" - "errors" -- "github.com/miekg/dns" - "io" - "time" -+ -+ "github.com/miekg/dns" - ) - - var ( -diff --git a/pkg/upstream/transport/utils.go b/pkg/upstream/transport/utils.go -index 870a88b..233f2a8 100644 ---- a/pkg/upstream/transport/utils.go -+++ b/pkg/upstream/transport/utils.go -@@ -20,10 +20,11 @@ - package transport - - import ( -- "github.com/miekg/dns" - "math/rand" -- "sync/atomic" -+ "sync" - "time" -+ -+ "github.com/miekg/dns" - ) - - func shadowCopy(m *dns.Msg) *dns.Msg { -@@ -94,10 +95,10 @@ func slicePopLatest[T any](s *[]T) (T, bool) { - } - - type idleTimer struct { -- d time.Duration -- updating atomic.Bool -- t *time.Timer -- stopped bool -+ d time.Duration -+ m sync.Mutex -+ t *time.Timer -+ stopped bool - } - - func newIdleTimer(d time.Duration, f func()) *idleTimer { -@@ -108,22 +109,29 @@ func newIdleTimer(d time.Duration, f func()) *idleTimer { - } - - func (t *idleTimer) reset(d time.Duration) { -- if t.updating.CompareAndSwap(false, true) { -- defer t.updating.Store(false) -- if t.stopped { -- return -- } -- if d <= 0 { -- d = t.d -- } -- if !t.t.Reset(t.d) { -- t.stopped = true -- // re-activated. stop it -- t.t.Stop() -- } -+ t.m.Lock() -+ defer t.m.Unlock() -+ if t.stopped { -+ return -+ } -+ -+ if d <= 0 { -+ d = t.d -+ } -+ -+ if !t.t.Reset(d) { -+ t.stopped = true -+ // re-activated. stop it -+ t.t.Stop() - } - } - - func (t *idleTimer) stop() { -+ t.m.Lock() -+ defer t.m.Unlock() -+ if t.stopped { -+ return -+ } -+ t.stopped = true - t.t.Stop() - } -diff --git a/pkg/upstream/upstream.go b/pkg/upstream/upstream.go -index 1bc80a2..ab77aba 100644 ---- a/pkg/upstream/upstream.go -+++ b/pkg/upstream/upstream.go -@@ -22,10 +22,12 @@ package upstream - import ( - "context" - "crypto/tls" -+ "errors" - "fmt" - "io" - "net" - "net/http" -+ "net/netip" - "net/url" - "strconv" - "strings" -@@ -42,10 +44,11 @@ import ( - "github.com/quic-go/quic-go/http3" - "go.uber.org/zap" - "golang.org/x/net/http2" -+ "golang.org/x/net/proxy" - ) - - const ( -- tlsHandshakeTimeout = time.Second * 5 -+ tlsHandshakeTimeout = time.Second * 3 - ) - - // Upstream represents a DNS upstream. -@@ -59,12 +62,17 @@ type Upstream interface { - - type Opt struct { - // DialAddr specifies the address the upstream will -- // actually dial to. -+ // actually dial to in the network layer by overwriting -+ // the address inferred from upstream url. -+ // It won't affect high level layers. (e.g. SNI, HTTP HOST header won't be changed). -+ // Can be an IP or a domain. Port is optional. -+ // Tips: If the upstream url host is a domain, specific an IP address -+ // here can skip resolving ip of this domain. - DialAddr string - - // Socks5 specifies the socks5 proxy server that the upstream - // will connect though. -- // Not implemented for udp upstreams and doh upstreams with http/3. -+ // Not implemented for udp based protocols (aka. dns over udp, http3, quic). - Socks5 string - - // SoMark sets the socket SO_MARK option in unix system. -@@ -75,40 +83,42 @@ type Opt struct { - - // IdleTimeout specifies the idle timeout for long-connections. - // Available for TCP, DoT, DoH. -- // If negative, TCP, DoT will not reuse connections. -- // Default: TCP, DoT: 10s , DoH: 30s. -+ // Default: TCP, DoT: 10s , DoH, DoQ: 30s. - IdleTimeout time.Duration - - // EnablePipeline enables query pipelining support as RFC 7766 6.2.1.1 suggested. - // Available for TCP, DoT upstream with IdleTimeout >= 0. -+ // Note: There is no fallback. - EnablePipeline bool - - // EnableHTTP3 enables HTTP/3 protocol for DoH upstream. -+ // Note: There is no fallback. - EnableHTTP3 bool - - // MaxConns limits the total number of connections, including connections - // in the dialing states. -- // Implemented for TCP/DoT pipeline enabled upstreams and DoH upstreams. -+ // Implemented for TCP/DoT pipeline enabled upstream and DoH upstream. - // Default is 2. - MaxConns int - -- // Bootstrap specifies a plain dns server for the go runtime to solve the -- // domain of the upstream server. It SHOULD be an IP address. Custom port -- // is supported. -- // Note: Use a domain address may cause dead resolve loop and additional -- // latency to dial upstream server. -- // HTTP3 is not supported. -+ // Bootstrap specifies a plain dns server to solve the -+ // upstream server domain address. -+ // It must be an IP address. Port is optional. - Bootstrap string - -+ // Bootstrap version. One of 0 (default equals 4), 4, 6. -+ // TODO: Support dual-stack. -+ BootstrapVer int -+ - // TLSConfig specifies the tls.Config that the TLS client will use. -- // Available for DoT, DoH upstreams. -+ // Available for DoT, DoH upstream. - TLSConfig *tls.Config - - // Logger specifies the logger that the upstream will use. - Logger *zap.Logger - - // EventObserver can observe connection events. -- // Note: Not Implemented for HTTP/3 upstreams. -+ // Not implemented for udp based protocols (dns over udp, http3, quic). - EventObserver EventObserver - } - -@@ -129,17 +139,127 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - return nil, fmt.Errorf("invalid server address, %w", err) - } - -+ // If host is a ipv6 without port, it will be in []. This will cause err when -+ // split and join address and port. Try to remove brackets now. -+ addrUrlHost := tryTrimIpv6Brackets(addrURL.Host) -+ - dialer := &net.Dialer{ -- Resolver: bootstrap.NewBootstrap(opt.Bootstrap), - Control: getSocketControlFunc(socketOpts{ - so_mark: opt.SoMark, - bind_to_device: opt.BindToDevice, - }), - } - -+ var bootstrapAp netip.AddrPort -+ if s := opt.Bootstrap; len(s) > 0 { -+ bootstrapAp, err = parseBootstrapAp(s) -+ if err != nil { -+ return nil, fmt.Errorf("invalid bootstrap, %w", err) -+ } -+ } -+ -+ newUdpAddrResolveFunc := func(defaultPort uint16) (func(ctx context.Context) (*net.UDPAddr, error), error) { -+ host, port, err := parseDialAddr(addrUrlHost, opt.DialAddr, defaultPort) -+ if err != nil { -+ return nil, err -+ } -+ -+ if addr, err := netip.ParseAddr(host); err == nil { // host is an ip. -+ ua := net.UDPAddrFromAddrPort(netip.AddrPortFrom(addr, port)) -+ return func(ctx context.Context) (*net.UDPAddr, error) { -+ return ua, nil -+ }, nil -+ } else { // Not an ip, assuming it's a domain name. -+ if bootstrapAp.IsValid() { -+ // Bootstrap enabled. -+ bs, err := bootstrap.New(host, port, bootstrapAp, opt.BootstrapVer, opt.Logger) -+ if err != nil { -+ return nil, err -+ } -+ -+ return func(ctx context.Context) (*net.UDPAddr, error) { -+ s, err := bs.GetAddrPortStr(ctx) -+ if err != nil { -+ return nil, fmt.Errorf("bootstrap failed, %w", err) -+ } -+ return net.ResolveUDPAddr("udp", s) -+ }, nil -+ } else { -+ // Bootstrap disabled. -+ dialAddr := joinPort(host, port) -+ return func(ctx context.Context) (*net.UDPAddr, error) { -+ return net.ResolveUDPAddr("udp", dialAddr) -+ }, nil -+ } -+ } -+ } -+ -+ newTcpDialer := func(dialAddrMustBeIp bool, defaultPort uint16) (func(ctx context.Context) (net.Conn, error), error) { -+ host, port, err := parseDialAddr(addrUrlHost, opt.DialAddr, defaultPort) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Socks5 enabled. -+ if s5Addr := opt.Socks5; len(s5Addr) > 0 { -+ socks5Dialer, err := proxy.SOCKS5("tcp", s5Addr, nil, dialer) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init socks5 dialer: %w", err) -+ } -+ -+ contextDialer := socks5Dialer.(proxy.ContextDialer) -+ dialAddr := net.JoinHostPort(host, strconv.Itoa(int(port))) -+ return func(ctx context.Context) (net.Conn, error) { -+ return contextDialer.DialContext(ctx, "tcp", dialAddr) -+ }, nil -+ } -+ -+ if _, err := netip.ParseAddr(host); err == nil { -+ // Host is an ip addr. No need to resolve it. -+ dialAddr := net.JoinHostPort(host, strconv.Itoa(int(port))) -+ return func(ctx context.Context) (net.Conn, error) { -+ return dialer.DialContext(ctx, "tcp", dialAddr) -+ }, nil -+ } else { -+ if dialAddrMustBeIp { -+ return nil, errors.New("addr must be an ip address") -+ } -+ // Host is not an ip addr, assuming it is a domain. -+ if bootstrapAp.IsValid() { -+ // Bootstrap enabled. -+ bs, err := bootstrap.New(host, port, bootstrapAp, opt.BootstrapVer, opt.Logger) -+ if err != nil { -+ return nil, err -+ } -+ -+ return func(ctx context.Context) (net.Conn, error) { -+ dialAddr, err := bs.GetAddrPortStr(ctx) -+ if err != nil { -+ return nil, fmt.Errorf("bootstrap failed, %w", err) -+ } -+ return dialer.DialContext(ctx, "tcp", dialAddr) -+ }, nil -+ } else { -+ // Bootstrap disabled. -+ dialAddr := net.JoinHostPort(host, strconv.Itoa(int(port))) -+ return func(ctx context.Context) (net.Conn, error) { -+ return dialer.DialContext(ctx, "tcp", dialAddr) -+ }, nil -+ } -+ } -+ } -+ - switch addrURL.Scheme { - case "", "udp": -- dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 53) -+ const defaultPort = 53 -+ host, port, err := parseDialAddr(addrUrlHost, opt.DialAddr, defaultPort) -+ if err != nil { -+ return nil, err -+ } -+ if _, err := netip.ParseAddr(host); err != nil { -+ return nil, fmt.Errorf("addr must be an ip address, %w", err) -+ } -+ dialAddr := joinPort(host, port) - uto := transport.IOOpts{ - DialFunc: func(ctx context.Context) (io.ReadWriteCloser, error) { - c, err := dialer.DialContext(ctx, "udp", dialAddr) -@@ -166,10 +286,14 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - t: transport.NewReuseConnTransport(transport.ReuseConnOpts{IOOpts: tto}), - }, nil - case "tcp": -- dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 53) -+ const defaultPort = 53 -+ tcpDialer, err := newTcpDialer(true, defaultPort) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init tcp dialer, %w", err) -+ } - to := transport.IOOpts{ - DialFunc: func(ctx context.Context) (io.ReadWriteCloser, error) { -- c, err := dialTCP(ctx, dialAddr, opt.Socks5, dialer) -+ c, err := tcpDialer(ctx) - c = wrapConn(c, opt.EventObserver) - return c, err - }, -@@ -182,18 +306,22 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - } - return transport.NewReuseConnTransport(transport.ReuseConnOpts{IOOpts: to}), nil - case "tls": -+ const defaultPort = 853 - tlsConfig := opt.TLSConfig.Clone() - if tlsConfig == nil { - tlsConfig = new(tls.Config) - } - if len(tlsConfig.ServerName) == 0 { -- tlsConfig.ServerName = tryRemovePort(addrURL.Host) -+ tlsConfig.ServerName = tryRemovePort(addrUrlHost) - } - -- dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 853) -+ tcpDialer, err := newTcpDialer(false, defaultPort) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init tcp dialer, %w", err) -+ } - to := transport.IOOpts{ - DialFunc: func(ctx context.Context) (io.ReadWriteCloser, error) { -- conn, err := dialTCP(ctx, dialAddr, opt.Socks5, dialer) -+ conn, err := tcpDialer(ctx) - if err != nil { - return nil, err - } -@@ -203,7 +331,6 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - tlsConn.Close() - return nil, err - } -- - return tlsConn, nil - }, - WriteFunc: dnsutils.WriteMsgToTCP, -@@ -215,6 +342,7 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - } - return transport.NewReuseConnTransport(transport.ReuseConnOpts{IOOpts: to}), nil - case "https": -+ const defaultPort = 443 - idleConnTimeout := time.Second * 30 - if opt.IdleTimeout > 0 { - idleConnTimeout = opt.IdleTimeout -@@ -224,41 +352,42 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - maxConn = opt.MaxConns - } - -- dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 443) - var t http.RoundTripper -- var addonCloser io.Closer // udpConn -+ var addonCloser io.Closer - if opt.EnableHTTP3 { -+ udpBootstrap, err := newUdpAddrResolveFunc(defaultPort) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init udp addr bootstrap, %w", err) -+ } -+ - lc := net.ListenConfig{Control: getSocketControlFunc(socketOpts{so_mark: opt.SoMark, bind_to_device: opt.BindToDevice})} - conn, err := lc.ListenPacket(context.Background(), "udp", "") - if err != nil { - return nil, fmt.Errorf("failed to init udp socket for quic") - } -- qt := &quic.Transport{ -+ quicTransport := &quic.Transport{ - Conn: conn, - } -- addonCloser = qt -+ addonCloser = quicTransport - t = &http3.RoundTripper{ - TLSClientConfig: opt.TLSConfig, -- QuicConfig: &quic.Config{ -- TokenStore: quic.NewLRUTokenStore(4, 8), -- InitialStreamReceiveWindow: 4 * 1024, -- MaxStreamReceiveWindow: 4 * 1024, -- InitialConnectionReceiveWindow: 8 * 1024, -- MaxConnectionReceiveWindow: 64 * 1024, -- }, -+ QuicConfig: newDefaultQuicConfig(), - Dial: func(ctx context.Context, _ string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { -- ua, err := net.ResolveUDPAddr("udp", dialAddr) // TODO: Support bootstrap. -+ ua, err := udpBootstrap(ctx) - if err != nil { - return nil, err - } -- -- return qt.DialEarly(ctx, ua, tlsCfg, cfg) -+ return quicTransport.DialEarly(ctx, ua, tlsCfg, cfg) - }, - } - } else { -+ tcpDialer, err := newTcpDialer(false, defaultPort) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init tcp dialer, %w", err) -+ } - t1 := &http.Transport{ - DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) { // overwrite server addr -- c, err := dialTCP(ctx, dialAddr, opt.Socks5, dialer) -+ c, err := tcpDialer(ctx) - c = wrapConn(c, opt.EventObserver) - return c, err - }, -@@ -281,26 +410,34 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - t = t1 - } - -- return &doh.Upstream{ -- EndPoint: addr, -- Client: &http.Client{Transport: t}, -- AddOnCloser: addonCloser, -+ return &dohWithClose{ -+ u: doh.NewUpstream(addr, &http.Client{Transport: t}), -+ closer: addonCloser, - }, nil - case "quic", "doq": -+ const defaultPort = 853 - tlsConfig := opt.TLSConfig.Clone() - if tlsConfig == nil { - tlsConfig = new(tls.Config) - } - if len(tlsConfig.ServerName) == 0 { -- tlsConfig.ServerName = tryRemovePort(addrURL.Host) -+ tlsConfig.ServerName = tryRemovePort(addrUrlHost) - } -+ tlsConfig.NextProtos = doq.DoqAlpn - -- quicConfig := &quic.Config{ -- TokenStore: quic.NewLRUTokenStore(4, 8), -- InitialStreamReceiveWindow: 4 * 1024, -- MaxStreamReceiveWindow: 4 * 1024, -- InitialConnectionReceiveWindow: 8 * 1024, -- MaxConnectionReceiveWindow: 64 * 1024, -+ quicConfig := newDefaultQuicConfig() -+ if opt.IdleTimeout > 0 { -+ quicConfig.MaxIdleTimeout = opt.IdleTimeout -+ } -+ -+ udpBootstrap, err := newUdpAddrResolveFunc(defaultPort) -+ if err != nil { -+ return nil, fmt.Errorf("failed to init udp addr bootstrap, %w", err) -+ } -+ -+ srk, err := doq.InitSrk() -+ if err != nil { -+ opt.Logger.Error("failed to init quic stateless reset key", zap.Error(err)) - } - - lc := net.ListenConfig{Control: getSocketControlFunc(socketOpts{so_mark: opt.SoMark, bind_to_device: opt.BindToDevice})} -@@ -309,35 +446,44 @@ func NewUpstream(addr string, opt Opt) (Upstream, error) { - return nil, fmt.Errorf("failed to init udp socket for quic") - } - -- dialAddr := getDialAddrWithPort(addrURL.Host, opt.DialAddr, 853) -- u, err := doq.NewUpstream(dialAddr, uc.(*net.UDPConn), tlsConfig, quicConfig) -- if err != nil { -- return nil, fmt.Errorf("failed to setup doq upstream, %w", err) -+ t := &quic.Transport{ -+ Conn: uc, -+ StatelessResetKey: (*quic.StatelessResetKey)(srk), - } -- return u, nil -- default: -- return nil, fmt.Errorf("unsupported protocol [%s]", addrURL.Scheme) -- } --} - --func getDialAddrWithPort(host, dialAddr string, defaultPort int) string { -- addr := host -- if len(dialAddr) > 0 { -- addr = dialAddr -- } -- _, _, err := net.SplitHostPort(addr) -- if err != nil { // no port, add it. -- return net.JoinHostPort(strings.Trim(addr, "[]"), strconv.Itoa(defaultPort)) -- } -- return addr --} -+ dialer := func(ctx context.Context) (quic.Connection, error) { -+ ua, err := udpBootstrap(ctx) -+ if err != nil { -+ return nil, fmt.Errorf("bootstrap failed, %w", err) -+ } -+ var c quic.Connection -+ ec, err := t.DialEarly(ctx, ua, tlsConfig, quicConfig) -+ if err != nil { -+ return nil, err -+ } - --func tryRemovePort(s string) string { -- host, _, err := net.SplitHostPort(s) -- if err != nil { -- return s -+ // This is a workaround to -+ // 1. recover from strange 0rtt rejected err. -+ // 2. avoid NextConnection might block forever. -+ // TODO: Remove this workaround. -+ select { -+ case <-ctx.Done(): -+ err := context.Cause(ctx) -+ ec.CloseWithError(0, "") -+ return nil, err -+ case <-ec.HandshakeComplete(): -+ c = ec.NextConnection() -+ } -+ return c, nil -+ } -+ -+ return &doqWithClose{ -+ u: doq.NewUpstream(dialer), -+ t: t, -+ }, nil -+ default: -+ return nil, fmt.Errorf("unsupported protocol [%s]", addrURL.Scheme) - } -- return host - } - - type udpWithFallback struct { -@@ -361,3 +507,48 @@ func (u *udpWithFallback) Close() error { - u.t.Close() - return nil - } -+ -+type doqWithClose struct { -+ u *doq.Upstream -+ t *quic.Transport -+} -+ -+func (u *doqWithClose) ExchangeContext(ctx context.Context, m *dns.Msg) (*dns.Msg, error) { -+ return u.u.ExchangeContext(ctx, m) -+} -+ -+func (u *doqWithClose) Close() error { -+ return u.t.Close() -+} -+ -+type dohWithClose struct { -+ u *doh.Upstream -+ closer io.Closer // maybe nil -+} -+ -+func (u *dohWithClose) ExchangeContext(ctx context.Context, m *dns.Msg) (*dns.Msg, error) { -+ return u.u.ExchangeContext(ctx, m) -+} -+ -+func (u *dohWithClose) Close() error { -+ if u.closer != nil { -+ return u.closer.Close() -+ } -+ return nil -+} -+ -+func newDefaultQuicConfig() *quic.Config { -+ return &quic.Config{ -+ TokenStore: quic.NewLRUTokenStore(4, 8), -+ -+ // Dns does not need large amount of io, so the rx/tx windows are small. -+ InitialStreamReceiveWindow: 4 * 1024, -+ MaxStreamReceiveWindow: 4 * 1024, -+ InitialConnectionReceiveWindow: 8 * 1024, -+ MaxConnectionReceiveWindow: 64 * 1024, -+ -+ MaxIdleTimeout: time.Second * 30, -+ KeepAlivePeriod: time.Second * 25, -+ HandshakeIdleTimeout: tlsHandshakeTimeout, -+ } -+} -diff --git a/pkg/upstream/upstream_test.go b/pkg/upstream/upstream_test.go -index 675b1ff..55e3b6d 100644 ---- a/pkg/upstream/upstream_test.go -+++ b/pkg/upstream/upstream_test.go -@@ -24,12 +24,13 @@ import ( - "crypto/tls" - "errors" - "fmt" -- "github.com/IrineSistiana/mosdns/v5/pkg/utils" -- "github.com/miekg/dns" - "net" - "sync" - "testing" - "time" -+ -+ "github.com/IrineSistiana/mosdns/v5/pkg/utils" -+ "github.com/miekg/dns" - ) - - func newUDPTestServer(t testing.TB, handler dns.Handler) (addr string, shutdownFunc func()) { -@@ -68,6 +69,9 @@ func newTCPTestServer(t testing.TB, handler dns.Handler) (addr string, shutdownF - func newDoTTestServer(t testing.TB, handler dns.Handler) (addr string, shutdownFunc func()) { - serverName := "test" - cert, err := utils.GenerateCertificate(serverName) -+ if err != nil { -+ t.Fatal(err) -+ } - tlsConfig := new(tls.Config) - tlsConfig.Certificates = []tls.Certificate{cert} - tlsListener, err := tls.Listen("tcp", "127.0.0.1:0", tlsConfig) -diff --git a/pkg/upstream/utils.go b/pkg/upstream/utils.go -index 7d297f3..8a42125 100644 ---- a/pkg/upstream/utils.go -+++ b/pkg/upstream/utils.go -@@ -20,10 +20,10 @@ - package upstream - - import ( -- "context" - "fmt" -- "golang.org/x/net/proxy" - "net" -+ "net/netip" -+ "strconv" - ) - - type socketOpts struct { -@@ -31,14 +31,70 @@ type socketOpts struct { - bind_to_device string - } - --func dialTCP(ctx context.Context, addr, socks5 string, dialer *net.Dialer) (net.Conn, error) { -- if len(socks5) > 0 { -- socks5Dialer, err := proxy.SOCKS5("tcp", socks5, nil, dialer) -+func parseDialAddr(urlHost, dialAddr string, defaultPort uint16) (string, uint16, error) { -+ addr := urlHost -+ if len(dialAddr) > 0 { -+ addr = dialAddr -+ } -+ host, port, err := trySplitHostPort(addr) -+ if err != nil { -+ return "", 0, err -+ } -+ if port == 0 { -+ port = defaultPort -+ } -+ return host, port, nil -+} -+ -+func joinPort(host string, port uint16) string { -+ return net.JoinHostPort(host, strconv.Itoa(int(port))) -+} -+ -+func tryRemovePort(s string) string { -+ host, _, err := net.SplitHostPort(s) -+ if err != nil { -+ return s -+ } -+ return host -+} -+ -+// trySplitHostPort splits host and port. -+// If s has no port, it returns s,0,nil -+func trySplitHostPort(s string) (string, uint16, error) { -+ var port uint16 -+ host, portS, err := net.SplitHostPort(s) -+ if err == nil { -+ n, err := strconv.ParseUint(portS, 10, 16) - if err != nil { -- return nil, fmt.Errorf("failed to init socks5 dialer: %w", err) -+ return "", 0, fmt.Errorf("invalid port, %w", err) - } -- return socks5Dialer.(proxy.ContextDialer).DialContext(ctx, "tcp", addr) -+ port = uint16(n) -+ return host, port, nil - } -+ return s, 0, nil -+} - -- return dialer.DialContext(ctx, "tcp", addr) -+func parseBootstrapAp(s string) (netip.AddrPort, error) { -+ host, port, err := trySplitHostPort(s) -+ if err != nil { -+ return netip.AddrPort{}, err -+ } -+ if port == 0 { -+ port = 53 -+ } -+ addr, err := netip.ParseAddr(host) -+ if err != nil { -+ return netip.AddrPort{}, err -+ } -+ return netip.AddrPortFrom(addr, port), nil -+} -+ -+func tryTrimIpv6Brackets(s string) string { -+ if len(s) < 2 { -+ return s -+ } -+ if s[0] == '[' && s[len(s)-1] == ']' { -+ return s[1 : len(s)-2] -+ } -+ return s - } -diff --git a/pkg/upstream/utils_unix.go b/pkg/upstream/utils_unix.go -index b8ced47..685a82b 100644 ---- a/pkg/upstream/utils_unix.go -+++ b/pkg/upstream/utils_unix.go -@@ -22,9 +22,10 @@ - package upstream - - import ( -- "golang.org/x/sys/unix" - "os" - "syscall" -+ -+ "golang.org/x/sys/unix" - ) - - func getSocketControlFunc(opts socketOpts) func(string, string, syscall.RawConn) error { -diff --git a/plugin/executable/forward/forward.go b/plugin/executable/forward/forward.go -index be39ad7..bba0da2 100644 ---- a/plugin/executable/forward/forward.go -+++ b/plugin/executable/forward/forward.go -@@ -24,6 +24,9 @@ import ( - "crypto/tls" - "errors" - "fmt" -+ "strings" -+ "time" -+ - "github.com/IrineSistiana/mosdns/v5/coremain" - "github.com/IrineSistiana/mosdns/v5/pkg/query_context" - "github.com/IrineSistiana/mosdns/v5/pkg/upstream" -@@ -32,8 +35,6 @@ import ( - "github.com/miekg/dns" - "github.com/prometheus/client_golang/prometheus" - "go.uber.org/zap" -- "strings" -- "time" - ) - - const PluginType = "forward" -@@ -57,6 +58,7 @@ type Args struct { - SoMark int `yaml:"so_mark"` - BindToDevice string `yaml:"bind_to_device"` - Bootstrap string `yaml:"bootstrap"` -+ BootstrapVer int `yaml:"bootstrap_version"` - } - - type UpstreamConfig struct { -@@ -73,6 +75,7 @@ type UpstreamConfig struct { - SoMark int `yaml:"so_mark"` - BindToDevice string `yaml:"bind_to_device"` - Bootstrap string `yaml:"bootstrap"` -+ BootstrapVer int `yaml:"bootstrap_version"` - } - - func Init(bp *coremain.BP, args any) (any, error) { -@@ -125,6 +128,7 @@ func NewForward(args *Args, opt Opts) (*Forward, error) { - utils.SetDefaultUnsignNum(&c.SoMark, args.SoMark) - utils.SetDefaultString(&c.BindToDevice, args.BindToDevice) - utils.SetDefaultString(&c.Bootstrap, args.Bootstrap) -+ utils.SetDefaultUnsignNum(&c.BootstrapVer, args.BootstrapVer) - } - - for i, c := range args.Upstreams { -@@ -144,6 +148,7 @@ func NewForward(args *Args, opt Opts) (*Forward, error) { - EnablePipeline: c.EnablePipeline, - EnableHTTP3: c.EnableHTTP3, - Bootstrap: c.Bootstrap, -+ BootstrapVer: c.BootstrapVer, - TLSConfig: &tls.Config{ - InsecureSkipVerify: c.InsecureSkipVerify, - ClientSessionCache: tls.NewLRUClientSessionCache(4), --- -2.34.8 - diff --git a/mosdns/patches/125-upstream-doq-send-STREAM-FIN-after-query-is-sent.patch b/mosdns/patches/125-upstream-doq-send-STREAM-FIN-after-query-is-sent.patch deleted file mode 100644 index e95e182..0000000 --- a/mosdns/patches/125-upstream-doq-send-STREAM-FIN-after-query-is-sent.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 1fa552cbe353e6467d33bd9366712ad150f06af0 Mon Sep 17 00:00:00 2001 -From: Irine Sistiana <49315432+IrineSistiana@users.noreply.github.com> -Date: Sat, 23 Sep 2023 14:29:25 +0800 -Subject: [PATCH 9/9] upstream/doq: send STREAM FIN after query is sent - -fixed #720 ---- - pkg/upstream/doq/upstream.go | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/pkg/upstream/doq/upstream.go b/pkg/upstream/doq/upstream.go -index 23d7f1c..78d30db 100644 ---- a/pkg/upstream/doq/upstream.go -+++ b/pkg/upstream/doq/upstream.go -@@ -242,6 +242,14 @@ func (u *Upstream) exchange(s quic.Stream, payload []byte) (*dns.Msg, error) { - return nil, err - } - -+ // RFC 9250 4.2 -+ // The client MUST send the DNS query over the selected stream and MUST -+ // indicate through the STREAM FIN mechanism that no further data will -+ // be sent on that stream. -+ // -+ // Call Close() here will send the STREAM FIN. It won't close Read. -+ s.Close() -+ - resp, _, err := dnsutils.ReadMsgFromTCP(s) - if err != nil { - return nil, err --- -2.34.8 - diff --git a/mosdns/patches/200-add-debug-log-again.patch b/mosdns/patches/200-add-debug-log-again.patch deleted file mode 100644 index c6cfc67..0000000 --- a/mosdns/patches/200-add-debug-log-again.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 3f57bcbf18fc5a537a4365ce1e5f5798db3a9dc6 Mon Sep 17 00:00:00 2001 -From: sbwml -Date: Sun, 25 Jun 2023 06:50:27 +0800 -Subject: [PATCH 10/10] add debug log again - ---- - pkg/server/http_handler.go | 1 + - pkg/server_handler/entry_handler.go | 2 ++ - pkg/upstream/bootstrap/bootstrap.go | 2 +- - plugin/executable/cache/cache.go | 3 +++ - 4 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/pkg/server/http_handler.go b/pkg/server/http_handler.go -index 58f5811..5fa76b4 100644 ---- a/pkg/server/http_handler.go -+++ b/pkg/server/http_handler.go -@@ -94,6 +94,7 @@ func (h *HttpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if err != nil { - h.warnErr(req, "invalid request", err) - w.WriteHeader(http.StatusBadRequest) -+ w.Write([]byte("Bad Request")) - return - } - -diff --git a/pkg/server_handler/entry_handler.go b/pkg/server_handler/entry_handler.go -index 520e3d2..38df952 100644 ---- a/pkg/server_handler/entry_handler.go -+++ b/pkg/server_handler/entry_handler.go -@@ -87,6 +87,8 @@ func (h *EntryHandler) Handle(ctx context.Context, q *dns.Msg, qInfo server.Quer - respMsg := qCtx.R() - if err != nil { - h.opts.Logger.Warn("entry err", qCtx.InfoField(), zap.Error(err)) -+ } else { -+ h.opts.Logger.Debug("entry returned", qCtx.InfoField()) - } - - if err == nil && respMsg == nil { -diff --git a/pkg/upstream/bootstrap/bootstrap.go b/pkg/upstream/bootstrap/bootstrap.go -index 2cd8ef9..5192053 100644 ---- a/pkg/upstream/bootstrap/bootstrap.go -+++ b/pkg/upstream/bootstrap/bootstrap.go -@@ -117,7 +117,7 @@ func (sp *Bootstrap) tryUpdate() { - if updateInterval < minimumUpdateInterval { - updateInterval = minimumUpdateInterval - } -- sp.logger.Info( -+ sp.logger.Debug( - "bootstrap addr updated", - zap.String("fqdn", sp.fqdn), - zap.Stringer("addr", addr), -diff --git a/plugin/executable/cache/cache.go b/plugin/executable/cache/cache.go -index 58162ee..dd833dc 100644 ---- a/plugin/executable/cache/cache.go -+++ b/plugin/executable/cache/cache.go -@@ -204,7 +204,10 @@ func (c *Cache) Exec(ctx context.Context, qCtx *query_context.Context, next sequ - c.hitTotal.Inc() - cachedResp.Id = q.Id // change msg id - shuffleIP(cachedResp) -+ c.logger.Debug("cache hit", qCtx.InfoField()) - qCtx.SetResponse(cachedResp) -+ } else { -+ c.logger.Debug("cache miss", qCtx.InfoField()) - } - - err := next.ExecNext(ctx, qCtx) --- -2.34.8 - diff --git a/mosdns/patches/203-compatible-with-go1.20.patch b/mosdns/patches/201-compatible-with-go1.20.patch similarity index 62% rename from mosdns/patches/203-compatible-with-go1.20.patch rename to mosdns/patches/201-compatible-with-go1.20.patch index 10d971a..175bbd3 100644 --- a/mosdns/patches/203-compatible-with-go1.20.patch +++ b/mosdns/patches/201-compatible-with-go1.20.patch @@ -1,18 +1,18 @@ -From a3b601abb667a4cc63039f26f634daa1b95f1d08 Mon Sep 17 00:00:00 2001 +From 329ba9ca89d25da58d1b51b8107f164beae816bb Mon Sep 17 00:00:00 2001 From: sbwml Date: Tue, 19 Sep 2023 21:15:12 +0800 -Subject: [PATCH] compatible with go1.20 +Subject: [PATCH 1/5] compatible with go1.20 --- - go.mod | 8 +++----- - go.sum | 20 ++++---------------- - 2 files changed, 7 insertions(+), 21 deletions(-) + go.mod | 6 ++---- + go.sum | 12 ++---------- + 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod -index f5cb30a..7c2b96a 100644 +index d4e5fa6..667aa2e 100644 --- a/go.mod +++ b/go.mod -@@ -1,15 +1,13 @@ +@@ -1,8 +1,6 @@ module github.com/IrineSistiana/mosdns/v5 -go 1.21 @@ -22,39 +22,20 @@ index f5cb30a..7c2b96a 100644 require ( github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57 - github.com/go-chi/chi/v5 v5.0.10 - github.com/google/nftables v0.1.0 - github.com/kardianos/service v1.2.2 -- github.com/klauspost/compress v1.16.7 -+ github.com/klauspost/compress v1.17.0 - github.com/miekg/dns v1.1.56 - github.com/mitchellh/mapstructure v1.5.0 - github.com/nadoo/ipset v0.5.0 @@ -46,7 +44,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mdlayher/netlink v1.7.2 // indirect - github.com/mdlayher/socket v0.5.0 // indirect + github.com/mdlayher/socket v0.4.1 // indirect - github.com/onsi/ginkgo/v2 v2.12.0 // indirect + github.com/onsi/ginkgo/v2 v2.12.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum -index 63c84d0..dd20043 100644 +index e0d143a..a74ec60 100644 --- a/go.sum +++ b/go.sum -@@ -38,10 +38,6 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f - dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= - github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= - github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= --github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686 h1:5R32cCep3VUDTKf3aurFKfgbvg+RScuBmZsw/DyyXco= --github.com/IrineSistiana/go-bytes-pool v0.0.0-20230419012903-2f1f26674686/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= --github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918113338-1af74a078e78 h1:Fem1OuBzs4A4kt/MPn09OjZKgphevSoBapSJR/40AzQ= --github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918113338-1af74a078e78/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= - github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57 h1:nfurUSSmVY9sY/mYyoReOA1w2cR2fp2eicL9ojicZhQ= - github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57/go.mod h1:pQ/FSsWSNYmNdgIKmulKlmVC/R2PEpq2vIEi3J9IijI= - github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a h1:GQdh/h0q0ni3L//CXusyk+7QdhBL289vdNaes1WKkHI= -@@ -69,7 +65,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y +@@ -65,7 +65,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -62,7 +43,7 @@ index 63c84d0..dd20043 100644 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -@@ -78,7 +73,6 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 +@@ -74,7 +73,6 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -70,14 +51,7 @@ index 63c84d0..dd20043 100644 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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -@@ -162,24 +156,22 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X - github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60= - github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= - github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= --github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= --github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -+github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -+github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +@@ -161,19 +159,17 @@ github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -99,31 +73,31 @@ index 63c84d0..dd20043 100644 github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -@@ -187,7 +179,6 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR - github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= - github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +@@ -181,7 +177,6 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR + github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= + github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -@@ -211,7 +202,6 @@ github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZa - github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= +@@ -205,7 +200,6 @@ github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3S + github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= - github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= - github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -@@ -256,7 +246,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= + github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= + github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +@@ -249,7 +243,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= + go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= + go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= - go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= - go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -@@ -573,7 +562,6 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw +@@ -564,7 +557,6 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -132,5 +106,5 @@ index 63c84d0..dd20043 100644 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -- -2.34.8 +2.42.0 diff --git a/mosdns/patches/202-change-log-level-to-Debug-in-bootstrap-address-updat.patch b/mosdns/patches/202-change-log-level-to-Debug-in-bootstrap-address-updat.patch new file mode 100644 index 0000000..44bad8d --- /dev/null +++ b/mosdns/patches/202-change-log-level-to-Debug-in-bootstrap-address-updat.patch @@ -0,0 +1,25 @@ +From 67d1b8f8c914a9b16d96ce0b712a08fc5e0f22d5 Mon Sep 17 00:00:00 2001 +From: sbwml +Date: Thu, 28 Sep 2023 16:41:18 +0800 +Subject: [PATCH 2/5] change log level to Debug in bootstrap address update + +--- + pkg/upstream/bootstrap/bootstrap.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkg/upstream/bootstrap/bootstrap.go b/pkg/upstream/bootstrap/bootstrap.go +index 2cd8ef9..5192053 100644 +--- a/pkg/upstream/bootstrap/bootstrap.go ++++ b/pkg/upstream/bootstrap/bootstrap.go +@@ -117,7 +117,7 @@ func (sp *Bootstrap) tryUpdate() { + if updateInterval < minimumUpdateInterval { + updateInterval = minimumUpdateInterval + } +- sp.logger.Info( ++ sp.logger.Debug( + "bootstrap addr updated", + zap.String("fqdn", sp.fqdn), + zap.Stringer("addr", addr), +-- +2.42.0 + diff --git a/mosdns/patches/203-add-response-for-bad-request-in-ServeHTTP-handler.patch b/mosdns/patches/203-add-response-for-bad-request-in-ServeHTTP-handler.patch new file mode 100644 index 0000000..463e96c --- /dev/null +++ b/mosdns/patches/203-add-response-for-bad-request-in-ServeHTTP-handler.patch @@ -0,0 +1,24 @@ +From 0b86b89629f32e7c8b859239aa1a4814f256053c Mon Sep 17 00:00:00 2001 +From: sbwml +Date: Thu, 28 Sep 2023 16:42:54 +0800 +Subject: [PATCH 3/5] add response for bad request in ServeHTTP handler + +--- + pkg/server/http_handler.go | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pkg/server/http_handler.go b/pkg/server/http_handler.go +index 5a41314..8f33b3f 100644 +--- a/pkg/server/http_handler.go ++++ b/pkg/server/http_handler.go +@@ -93,6 +93,7 @@ func (h *HttpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if err != nil { + h.warnErr(req, "invalid request", err) + w.WriteHeader(http.StatusBadRequest) ++ w.Write([]byte("Bad Request")) + return + } + +-- +2.42.0 + diff --git a/mosdns/patches/201-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch b/mosdns/patches/204-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch similarity index 89% rename from mosdns/patches/201-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch rename to mosdns/patches/204-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch index 48401bd..f623815 100644 --- a/mosdns/patches/201-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch +++ b/mosdns/patches/204-black_hole-apply-Fisher-Yates-shuffle-algorithm-to-r.patch @@ -1,8 +1,8 @@ -From 6c00597904ba487615e3a49626ccbb7d5623283f Mon Sep 17 00:00:00 2001 +From e34dca717e78d24a84b98c2b5d371c4253b7e260 Mon Sep 17 00:00:00 2001 From: sbwml Date: Wed, 20 Sep 2023 14:51:19 +0800 -Subject: [PATCH] black_hole: apply Fisher-Yates shuffle algorithm to randomize - IP order +Subject: [PATCH 4/5] black_hole: apply Fisher-Yates shuffle algorithm to + randomize IP order --- plugin/executable/black_hole/black_hole.go | 15 +++++++++++++++ @@ -52,5 +52,5 @@ index 775253d..f955019 100644 qCtx.SetResponse(r) } -- -2.34.8 +2.42.0 diff --git a/mosdns/patches/202-format-logtime.patch b/mosdns/patches/205-format-logtime.patch similarity index 91% rename from mosdns/patches/202-format-logtime.patch rename to mosdns/patches/205-format-logtime.patch index fe74c46..204bc8e 100644 --- a/mosdns/patches/202-format-logtime.patch +++ b/mosdns/patches/205-format-logtime.patch @@ -1,7 +1,7 @@ -From a53f4d9a5994e28be07c832308160d4cc17f604f Mon Sep 17 00:00:00 2001 +From 2dc08749e2de8f19ef869e7f89c9979edbbc71ff Mon Sep 17 00:00:00 2001 From: sbwml Date: Wed, 20 Sep 2023 21:05:18 +0800 -Subject: [PATCH] format logtime +Subject: [PATCH 5/5] format logtime --- mlog/logger.go | 18 ++++++++++++++---- @@ -47,5 +47,5 @@ index 861f091..1508db0 100644 // L is a global logger. -- -2.34.8 +2.42.0