MCPcopy
hub / github.com/AdguardTeam/dnsproxy / handleQUICStream

Method handleQUICStream

proxy/serverquic.go:312–386  ·  view source on GitHub ↗

handleQUICStream reads DNS queries from the stream, processes them, and writes back the response.

(ctx context.Context, stream *quic.Stream, conn *quic.Conn)

Source from the content-addressed store, hash-verified

310// handleQUICStream reads DNS queries from the stream, processes them,
311// and writes back the response.
312func (p *Proxy) handleQUICStream(ctx context.Context, stream *quic.Stream, conn *quic.Conn) {
313 bufPtr := p.bytesPool.Get()
314 defer p.bytesPool.Put(bufPtr)
315
316 ctx, cancel := p.reqCtx.New(ctx)
317 defer cancel()
318
319 // One query - one stream.
320 // The client MUST select the next available client-initiated bidirectional
321 // stream for each subsequent query on a QUIC connection.
322
323 // err is not checked here because STREAM FIN sent by the client is
324 // indicated as error here. Instead, we should check the number of bytes
325 // received.
326 buf := *bufPtr
327 n, err := readAll(stream, buf)
328
329 // Note that io.EOF does not really mean that there's any error, this is
330 // just a signal that there will be no data to read anymore from this
331 // stream.
332 if (err != nil && err != io.EOF) || n < minDNSPacketSize {
333 logShortQUICRead(ctx, err, p.logger)
334
335 return
336 }
337
338 // In theory, we should use ALPN to get the DoQ version properly. However,
339 // since there are not too many versions now, we only check how the DNS
340 // query is encoded. If it's sent with a 2-byte prefix, we consider this a
341 // DoQ v1. Otherwise, a draft version.
342 doqVersion := DoQv1
343 req := &dns.Msg{}
344
345 // Note that we support both the old drafts and the new RFC. In the old
346 // draft DNS messages were not prefixed with the message length.
347 packetLen := binary.BigEndian.Uint16(buf[:2])
348 if packetLen == uint16(n-2) {
349 err = req.Unpack(buf[2:n])
350 } else {
351 err = req.Unpack(buf[:n])
352 doqVersion = DoQv1Draft
353 }
354
355 if err != nil {
356 p.logger.ErrorContext(ctx, "unpacking quic packet", slogutil.KeyError, err)
357 closeQUICConn(conn, DoQCodeProtocolError, p.logger)
358
359 return
360 }
361
362 if !validQUICMsg(req, p.logger) {
363 // If a peer encounters such an error condition, it is considered a
364 // fatal error. It SHOULD forcibly abort the connection using QUIC's
365 // CONNECTION_CLOSE mechanism and SHOULD use the DoQ error code
366 // DOQ_PROTOCOL_ERROR.
367 closeQUICConn(conn, DoQCodeProtocolError, p.logger)
368
369 return

Callers 1

handleQUICConnectionMethod · 0.95

Calls 6

newDNSContextMethod · 0.95
handleDNSRequestMethod · 0.95
readAllFunction · 0.85
logShortQUICReadFunction · 0.85
closeQUICConnFunction · 0.85
validQUICMsgFunction · 0.85

Tested by

no test coverage detected