@ -1059,10 +1059,15 @@ func (ns *Impl) acceptUDP(r *udp.ForwarderRequest) {
go ns . forwardUDP ( c , srcAddr , dstAddr )
go ns . forwardUDP ( c , srcAddr , dstAddr )
}
}
// Buffer pool for forwarding UDP packets.
var udpBufPool = & sync . Pool {
New : func ( ) any {
b := make ( [ ] byte , maxUDPPacketSize )
return & b
} ,
}
func ( ns * Impl ) handleMagicDNSUDP ( srcAddr netip . AddrPort , c * gonet . UDPConn ) {
func ( ns * Impl ) handleMagicDNSUDP ( srcAddr netip . AddrPort , c * gonet . UDPConn ) {
// In practice, implementations are advised not to exceed 512 bytes
// due to fragmenting. Just to be sure, we bump all the way to the MTU.
var maxUDPReqSize = tstun . DefaultMTU ( )
// Packets are being generated by the local host, so there should be
// Packets are being generated by the local host, so there should be
// very, very little latency. 150ms was chosen as something of an upper
// very, very little latency. 150ms was chosen as something of an upper
// bound on resource usage, while hopefully still being long enough for
// bound on resource usage, while hopefully still being long enough for
@ -1070,7 +1075,10 @@ func (ns *Impl) handleMagicDNSUDP(srcAddr netip.AddrPort, c *gonet.UDPConn) {
const readDeadline = 150 * time . Millisecond
const readDeadline = 150 * time . Millisecond
defer c . Close ( )
defer c . Close ( )
q := make ( [ ] byte , maxUDPReqSize )
bufp := udpBufPool . Get ( ) . ( * [ ] byte )
defer udpBufPool . Put ( bufp )
q := * bufp
// libresolv from glibc is quite adamant that transmitting multiple DNS
// libresolv from glibc is quite adamant that transmitting multiple DNS
// requests down the same UDP socket is valid. To support this, we read
// requests down the same UDP socket is valid. To support this, we read
@ -1183,7 +1191,11 @@ func startPacketCopy(ctx context.Context, cancel context.CancelFunc, dst net.Pac
}
}
go func ( ) {
go func ( ) {
defer cancel ( ) // tear down the other direction's copy
defer cancel ( ) // tear down the other direction's copy
pkt := make ( [ ] byte , maxUDPPacketSize )
bufp := udpBufPool . Get ( ) . ( * [ ] byte )
defer udpBufPool . Put ( bufp )
pkt := * bufp
for {
for {
select {
select {
case <- ctx . Done ( ) :
case <- ctx . Done ( ) :