all: Use Go 1.21, new QUIC API (#9040)

This commit is contained in:
Jakob Borg
2023-08-21 15:25:52 +02:00
committed by GitHub
parent c40dae315b
commit cbf0e31f69
8 changed files with 139 additions and 122 deletions
+19 -63
View File
@@ -9,10 +9,8 @@ package stun
import (
"context"
"net"
"sync/atomic"
"time"
"github.com/AudriusButkevicius/pfilter"
"github.com/ccding/go-stun/stun"
"github.com/syncthing/syncthing/lib/config"
@@ -21,8 +19,10 @@ import (
const stunRetryInterval = 5 * time.Minute
type Host = stun.Host
type NATType = stun.NATType
type (
Host = stun.Host
NATType = stun.NATType
)
// NAT types.
@@ -38,38 +38,6 @@ const (
NATSymmetricUDPFirewall = stun.NATSymmetricUDPFirewall
)
type writeTrackingUdpConn struct {
// Needs to be UDPConn not PacketConn, as pfilter checks for WriteMsgUDP/ReadMsgUDP
// and even if we embed UDPConn here, in place of a PacketConn, seems the interface
// check fails.
*net.UDPConn
lastWrite atomic.Int64
}
func (c *writeTrackingUdpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
c.lastWrite.Store(time.Now().Unix())
return c.UDPConn.WriteTo(p, addr)
}
func (c *writeTrackingUdpConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) {
c.lastWrite.Store(time.Now().Unix())
return c.UDPConn.WriteMsgUDP(b, oob, addr)
}
func (c *writeTrackingUdpConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) {
c.lastWrite.Store(time.Now().Unix())
return c.UDPConn.WriteToUDP(b, addr)
}
func (c *writeTrackingUdpConn) Write(b []byte) (int, error) {
c.lastWrite.Store(time.Now().Unix())
return c.UDPConn.Write(b)
}
func (c *writeTrackingUdpConn) getLastWrite() time.Time {
return time.Unix(c.lastWrite.Load(), 0)
}
type Subscriber interface {
OnNATTypeChanged(natType NATType)
OnExternalAddressChanged(address *Host, via string)
@@ -79,30 +47,21 @@ type Service struct {
name string
cfg config.Wrapper
subscriber Subscriber
stunConn net.PacketConn
client *stun.Client
writeTrackingUdpConn *writeTrackingUdpConn
lastWriter LastWriter
natType NATType
addr *Host
}
func New(cfg config.Wrapper, subscriber Subscriber, conn *net.UDPConn) (*Service, net.PacketConn) {
// Wrap the original connection to track writes on it
writeTrackingUdpConn := &writeTrackingUdpConn{UDPConn: conn}
// Wrap it in a filter and split it up, so that stun packets arrive on stun conn, others arrive on the data conn
filterConn := pfilter.NewPacketFilter(writeTrackingUdpConn)
otherDataConn := filterConn.NewConn(otherDataPriority, nil)
stunConn := filterConn.NewConn(stunFilterPriority, &stunFilter{
ids: make(map[string]time.Time),
})
filterConn.Start()
type LastWriter interface {
LastWrite() time.Time
}
func New(cfg config.Wrapper, subscriber Subscriber, conn net.PacketConn, lastWriter LastWriter) *Service {
// Construct the client to use the stun conn
client := stun.NewClientWithConnection(stunConn)
client := stun.NewClientWithConnection(conn)
client.SetSoftwareName("") // Explicitly unset this, seems to freak some servers out.
// Return the service and the other conn to the client
@@ -117,15 +76,14 @@ func New(cfg config.Wrapper, subscriber Subscriber, conn *net.UDPConn) (*Service
cfg: cfg,
subscriber: subscriber,
stunConn: stunConn,
client: client,
writeTrackingUdpConn: writeTrackingUdpConn,
lastWriter: lastWriter,
natType: NATUnknown,
addr: nil,
}
return s, otherDataConn
return s
}
func (s *Service) Serve(ctx context.Context) error {
@@ -134,13 +92,6 @@ func (s *Service) Serve(ctx context.Context) error {
s.setExternalAddress(nil, "")
}()
// Closing s.stunConn unblocks operations that use the connection
// (Discover, Keepalive) and might otherwise block us from returning.
go func() {
<-ctx.Done()
_ = s.stunConn.Close()
}()
timer := time.NewTimer(time.Millisecond)
for {
@@ -244,6 +195,7 @@ func (s *Service) stunKeepAlive(ctx context.Context, addr string, extAddr *Host)
l.Debugf("%s starting stun keepalive via %s, next sleep %s", s, addr, nextSleep)
var ourLastWrite time.Time
for {
if areDifferent(s.addr, extAddr) {
// If the port has changed (addresses are not equal but the hosts are equal),
@@ -264,7 +216,10 @@ func (s *Service) stunKeepAlive(ctx context.Context, addr string, extAddr *Host)
}
// Adjust the keepalives to fire only nextSleep after last write.
lastWrite := s.writeTrackingUdpConn.getLastWrite()
lastWrite := ourLastWrite
if quicLastWrite := s.lastWriter.LastWrite(); quicLastWrite.After(lastWrite) {
lastWrite = quicLastWrite
}
minSleep := time.Duration(s.cfg.Options().StunKeepaliveMinS) * time.Second
if nextSleep < minSleep {
nextSleep = minSleep
@@ -293,7 +248,7 @@ func (s *Service) stunKeepAlive(ctx context.Context, addr string, extAddr *Host)
}
// Check if any writes happened while we were sleeping, if they did, sleep again
lastWrite = s.writeTrackingUdpConn.getLastWrite()
lastWrite = s.lastWriter.LastWrite()
if gap := time.Since(lastWrite); gap < nextSleep {
l.Debugf("%s stun last write gap less than next sleep: %s < %s. Will try later", s, gap, nextSleep)
goto tryLater
@@ -306,6 +261,7 @@ func (s *Service) stunKeepAlive(ctx context.Context, addr string, extAddr *Host)
l.Debugf("%s stun keepalive on %s: %s (%v)", s, addr, err, extAddr)
return
}
ourLastWrite = time.Now()
}
}