Skip to content

Commit 638288e

Browse files
committed
Pull request: all: upd golibs
Squashed commit of the following: commit 9b7e21e Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Dec 12 10:05:31 2023 +0200 proxy: imp code commit d5b40a4 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Dec 11 12:02:26 2023 +0200 all: upd golibs
1 parent afd2d3e commit 638288e

12 files changed

Lines changed: 82 additions & 101 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Application Options:
9090
--ipv6-disabled If specified, all AAAA requests will be replied with NoError RCode and empty answer
9191
--bogus-nxdomain= Transform the responses containing at least a single IP that matches specified addresses and CIDRs into NXDOMAIN. Can be specified multiple times.
9292
--udp-buf-size= Set the size of the UDP buffer in bytes. A value <= 0 will use the system default.
93-
--max-go-routines= Set the maximum number of go routines. A value <= 0 will not not set a maximum.
93+
--max-go-routines= Set the maximum number of go routines. A zero value will not not set a maximum.
9494
--pprof If present, exposes pprof information on localhost:6060.
9595
--version Prints the program version
9696

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/AdguardTeam/dnsproxy
33
go 1.20
44

55
require (
6-
github.com/AdguardTeam/golibs v0.18.0
6+
github.com/AdguardTeam/golibs v0.18.1
77
github.com/ameshkov/dnscrypt/v2 v2.2.7
88
github.com/ameshkov/dnsstamps v1.0.3
99
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
github.com/AdguardTeam/golibs v0.18.0 h1:ckS2YK7t2Ub6UkXl0fnreVaM15Zb07Hh1gmFqttjpWg=
2-
github.com/AdguardTeam/golibs v0.18.0/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
1+
github.com/AdguardTeam/golibs v0.18.1 h1:6u0fvrIj2qjUsRdbIGJ9AR0g5QRSWdKIo/DYl3tp5aM=
2+
github.com/AdguardTeam/golibs v0.18.1/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
33
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
44
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
55
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ type Options struct {
196196
// UDP buffer size value
197197
UDPBufferSize int `yaml:"udp-buf-size" long:"udp-buf-size" description:"Set the size of the UDP buffer in bytes. A value <= 0 will use the system default."`
198198

199-
// The maximum number of go routines
200-
MaxGoRoutines int `yaml:"max-go-routines" long:"max-go-routines" description:"Set the maximum number of go routines. A value <= 0 will not not set a maximum."`
199+
// MaxGoRoutines is the maximum number of goroutines.
200+
MaxGoRoutines uint `yaml:"max-go-routines" long:"max-go-routines" description:"Set the maximum number of go routines. A zero value will not not set a maximum."`
201201

202202
// Pprof defines whether the pprof information needs to be exposed via
203203
// localhost:6060 or not.

proxy/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ type Config struct {
182182
// TODO(a.garipov): Rename this to something like
183183
// “MaxDNSRequestGoroutines” in a later major version, as it doesn't
184184
// actually limit all goroutines.
185-
MaxGoroutines int
185+
MaxGoroutines uint
186186

187187
// The size of the read buffer on the underlying socket. Larger read buffers can handle
188188
// larger bursts of requests before packets get dropped.

proxy/proxy.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/AdguardTeam/golibs/errors"
2020
"github.com/AdguardTeam/golibs/log"
2121
"github.com/AdguardTeam/golibs/netutil"
22+
"github.com/AdguardTeam/golibs/syncutil"
2223
"github.com/ameshkov/dnscrypt/v2"
2324
"github.com/miekg/dns"
2425
gocache "github.com/patrickmn/go-cache"
@@ -166,15 +167,15 @@ type Proxy struct {
166167
// RWMutex protects the whole proxy.
167168
sync.RWMutex
168169

169-
// requestGoroutinesSema limits the number of simultaneous requests.
170+
// requestsSema limits the number of simultaneous requests.
170171
//
171172
// TODO(a.garipov): Currently we have to pass this exact semaphore to
172173
// the workers, to prevent races on restart. In the future we will need
173174
// a better restarting mechanism that completely prevents such invalid
174175
// states.
175176
//
176177
// See also: https://github.com/AdguardTeam/AdGuardHome/issues/2242.
177-
requestGoroutinesSema semaphore
178+
requestsSema syncutil.Semaphore
178179

179180
// Config is the proxy configuration.
180181
//
@@ -195,12 +196,9 @@ func (p *Proxy) Init() (err error) {
195196
if p.MaxGoroutines > 0 {
196197
log.Info("dnsproxy: max goroutines is set to %d", p.MaxGoroutines)
197198

198-
p.requestGoroutinesSema, err = newChanSemaphore(p.MaxGoroutines)
199-
if err != nil {
200-
return fmt.Errorf("can't init semaphore: %w", err)
201-
}
199+
p.requestsSema = syncutil.NewChanSemaphore(p.MaxGoroutines)
202200
} else {
203-
p.requestGoroutinesSema = newNoopSemaphore()
201+
p.requestsSema = syncutil.EmptySemaphore{}
204202
}
205203

206204
p.udpOOBSize = proxynetutil.UDPGetOOBSize()

proxy/sema.go

Lines changed: 0 additions & 58 deletions
This file was deleted.

proxy/server.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ func (p *Proxy) startListeners(ctx context.Context) error {
4444
}
4545

4646
for _, l := range p.udpListen {
47-
go p.udpPacketLoop(l, p.requestGoroutinesSema)
47+
go p.udpPacketLoop(l, p.requestsSema)
4848
}
4949

5050
for _, l := range p.tcpListen {
51-
go p.tcpPacketLoop(l, ProtoTCP, p.requestGoroutinesSema)
51+
go p.tcpPacketLoop(l, ProtoTCP, p.requestsSema)
5252
}
5353

5454
for _, l := range p.tlsListen {
55-
go p.tcpPacketLoop(l, ProtoTLS, p.requestGoroutinesSema)
55+
go p.tcpPacketLoop(l, ProtoTLS, p.requestsSema)
5656
}
5757

5858
for _, l := range p.httpsListen {
@@ -64,7 +64,7 @@ func (p *Proxy) startListeners(ctx context.Context) error {
6464
}
6565

6666
for _, l := range p.quicListen {
67-
go p.quicPacketLoop(l, p.requestGoroutinesSema)
67+
go p.quicPacketLoop(l, p.requestsSema)
6868
}
6969

7070
for _, l := range p.dnsCryptUDPListen {

proxy/server_dnscrypt.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package proxy
22

33
import (
4+
"context"
45
"fmt"
56
"net"
67

78
"github.com/AdguardTeam/golibs/errors"
89
"github.com/AdguardTeam/golibs/log"
910
"github.com/AdguardTeam/golibs/netutil"
11+
"github.com/AdguardTeam/golibs/syncutil"
1012
"github.com/ameshkov/dnscrypt/v2"
1113
"github.com/miekg/dns"
1214
)
@@ -28,7 +30,7 @@ func (p *Proxy) createDNSCryptListeners() (err error) {
2830
Handler: &dnsCryptHandler{
2931
proxy: p,
3032

31-
requestGoroutinesSema: p.requestGoroutinesSema,
33+
reqSema: p.requestsSema,
3234
},
3335
}
3436

@@ -61,20 +63,24 @@ func (p *Proxy) createDNSCryptListeners() (err error) {
6163
type dnsCryptHandler struct {
6264
proxy *Proxy
6365

64-
requestGoroutinesSema semaphore
66+
reqSema syncutil.Semaphore
6567
}
6668

6769
// compile-time type check
6870
var _ dnscrypt.Handler = &dnsCryptHandler{}
6971

7072
// ServeDNS - processes the DNS query
71-
func (h *dnsCryptHandler) ServeDNS(rw dnscrypt.ResponseWriter, req *dns.Msg) error {
73+
func (h *dnsCryptHandler) ServeDNS(rw dnscrypt.ResponseWriter, req *dns.Msg) (err error) {
7274
d := h.proxy.newDNSContext(ProtoDNSCrypt, req)
7375
d.Addr = netutil.NetAddrToAddrPort(rw.RemoteAddr())
7476
d.DNSCryptResponseWriter = rw
7577

76-
h.requestGoroutinesSema.acquire()
77-
defer h.requestGoroutinesSema.release()
78+
// TODO(d.kolyshev): Pass and use context from above.
79+
err = h.reqSema.Acquire(context.Background())
80+
if err != nil {
81+
return fmt.Errorf("dnsproxy: dnscrypt: acquiring semaphore: %w", err)
82+
}
83+
defer h.reqSema.Release()
7884

7985
return h.proxy.handleDNSRequest(d)
8086
}

proxy/server_quic.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/AdguardTeam/golibs/errors"
1414
"github.com/AdguardTeam/golibs/log"
1515
"github.com/AdguardTeam/golibs/netutil"
16+
"github.com/AdguardTeam/golibs/syncutil"
1617
"github.com/bluele/gcache"
1718
"github.com/miekg/dns"
1819
"github.com/quic-go/quic-go"
@@ -82,11 +83,12 @@ func (p *Proxy) createQUICListeners() error {
8283

8384
// quicPacketLoop listens for incoming QUIC packets.
8485
//
85-
// See also the comment on Proxy.requestGoroutinesSema.
86-
func (p *Proxy) quicPacketLoop(l *quic.EarlyListener, requestGoroutinesSema semaphore) {
86+
// See also the comment on Proxy.requestsSema.
87+
func (p *Proxy) quicPacketLoop(l *quic.EarlyListener, reqSema syncutil.Semaphore) {
8788
log.Info("Entering the DNS-over-QUIC listener loop on %s", l.Addr())
8889
for {
89-
conn, err := l.Accept(context.Background())
90+
ctx := context.Background()
91+
conn, err := l.Accept(ctx)
9092
if err != nil {
9193
if isQUICErrorForDebugLog(err) {
9294
log.Debug("accepting quic conn: closed or timed out: %s", err)
@@ -97,26 +99,34 @@ func (p *Proxy) quicPacketLoop(l *quic.EarlyListener, requestGoroutinesSema sema
9799
break
98100
}
99101

100-
requestGoroutinesSema.acquire()
102+
err = reqSema.Acquire(ctx)
103+
if err != nil {
104+
log.Error("dnsproxy: quic: acquiring semaphore: %s", err)
105+
106+
break
107+
}
101108
go func() {
102-
p.handleQUICConnection(conn, requestGoroutinesSema)
103-
requestGoroutinesSema.release()
109+
defer reqSema.Release()
110+
111+
p.handleQUICConnection(conn, reqSema)
104112
}()
105113
}
106114
}
107115

108116
// handleQUICConnection handles a new QUIC connection. It waits for new streams
109117
// and passes them to handleQUICStream.
110118
//
111-
// See also the comment on Proxy.requestGoroutinesSema.
112-
func (p *Proxy) handleQUICConnection(conn quic.Connection, requestGoroutinesSema semaphore) {
119+
// See also the comment on Proxy.requestsSema.
120+
func (p *Proxy) handleQUICConnection(conn quic.Connection, reqSema syncutil.Semaphore) {
113121
for {
122+
ctx := context.Background()
123+
114124
// The stub to resolver DNS traffic follows a simple pattern in which
115125
// the client sends a query, and the server provides a response. This
116126
// design specifies that for each subsequent query on a QUIC connection
117127
// the client MUST select the next available client-initiated
118128
// bidirectional stream.
119-
stream, err := conn.AcceptStream(context.Background())
129+
stream, err := conn.AcceptStream(ctx)
120130
if err != nil {
121131
if isQUICErrorForDebugLog(err) {
122132
log.Debug("accepting quic stream: closed or timed out: %s", err)
@@ -130,16 +140,24 @@ func (p *Proxy) handleQUICConnection(conn quic.Connection, requestGoroutinesSema
130140
return
131141
}
132142

133-
requestGoroutinesSema.acquire()
143+
err = reqSema.Acquire(ctx)
144+
if err != nil {
145+
log.Error("dnsproxy: quic: acquiring semaphore: %s", err)
146+
147+
// Close the connection to make sure resources are freed.
148+
closeQUICConn(conn, DoQCodeNoError)
149+
150+
return
151+
}
134152
go func() {
153+
defer reqSema.Release()
154+
135155
p.handleQUICStream(stream, conn)
136156

137157
// The server MUST send the response(s) on the same stream and MUST
138158
// indicate, after the last response, through the STREAM FIN
139159
// mechanism that no further data will be sent on that stream.
140160
_ = stream.Close()
141-
142-
requestGoroutinesSema.release()
143161
}()
144162
}
145163
}

0 commit comments

Comments
 (0)