Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 00:30 UTC
core: Embed net.UDPConn to gain optimizations (#5606)
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
WeidiDeng committed
Jul 1, 2023 at 06:31 UTC
710824c3ce9f8084517e8ab099d57f9060f62061
1 file changed
+17
-23
listeners.go
+17
-23
@@ -196,7 +196,8 @@ func (na NetworkAddress) listen(ctx context.Context, portOffset uint, config net
196
if err != nil {
197
return nil, err
198
}
199
- ln = &fakeClosePacketConn{sharedPacketConn: sharedPc.(*sharedPacketConn)}
199
+ spc := sharedPc.(*sharedPacketConn)
200
+ ln = &fakeClosePacketConn{spc: spc, UDPConn: spc.PacketConn.(*net.UDPConn)}
201
}
202
if strings.HasPrefix(na.Network, "ip") {
203
ln, err = config.ListenPacket(ctx, na.Network, address)
@@ -668,37 +669,30 @@ func fakeClosedErr(l interface{ Addr() net.Addr }) error {
669
// socket is actually left open.
670
var errFakeClosed = fmt.Errorf("listener 'closed' 😉")
671
671
-// fakeClosePacketConn is like fakeCloseListener, but for PacketConns.
672
+// fakeClosePacketConn is like fakeCloseListener, but for PacketConns,
673
+// or more specifically, *net.UDPConn
674
type fakeClosePacketConn struct {
673
- closed int32 // accessed atomically; belongs to this struct only
674
- *sharedPacketConn // embedded, so we also become a net.PacketConn
675
+ closed int32 // accessed atomically; belongs to this struct only
676
+ spc *sharedPacketConn // its key is used in Close
677
+ *net.UDPConn // embedded, so we also become a net.PacketConn and enable several other optimizations done by quic-go
678
}
679
680
+// interface guard for extra optimizations
681
+// needed by QUIC implementation: https://github.com/caddyserver/caddy/issues/3998, https://github.com/caddyserver/caddy/issues/5605
682
+var _ quic.OOBCapablePacketConn = (*fakeClosePacketConn)(nil)
683
+
684
+// https://pkg.go.dev/golang.org/x/net/ipv4#NewPacketConn is used by quic-go and requires a net.PacketConn type assertable to a net.Conn,
685
+// but doesn't actually use these methods, the only methods needed are `ReadMsgUDP` and `SyscallConn`.
686
+var _ net.Conn = (*fakeClosePacketConn)(nil)
687
+
688
+// Close won't close the underlying socket unless there is no more reference, then listenerPool will close it.
689
func (fcpc *fakeClosePacketConn) Close() error {
690
if atomic.CompareAndSwapInt32(&fcpc.closed, 0, 1) {
679
- _, _ = listenerPool.Delete(fcpc.sharedPacketConn.key)
691
+ _, _ = listenerPool.Delete(fcpc.spc.key)
692
}
693
return nil
694
}
695
684
-// Supports QUIC implementation: https://github.com/caddyserver/caddy/issues/3998
685
-func (fcpc fakeClosePacketConn) SetReadBuffer(bytes int) error {
686
- if conn, ok := fcpc.PacketConn.(interface{ SetReadBuffer(int) error }); ok {
687
- return conn.SetReadBuffer(bytes)
688
- }
689
- return fmt.Errorf("SetReadBuffer() not implemented for %T", fcpc.PacketConn)
690
-}
691
-
692
-// Supports QUIC implementation: https://github.com/caddyserver/caddy/issues/3998
693
-func (fcpc fakeClosePacketConn) SyscallConn() (syscall.RawConn, error) {
694
- if conn, ok := fcpc.PacketConn.(interface {
695
- SyscallConn() (syscall.RawConn, error)
696
- }); ok {
697
- return conn.SyscallConn()
698
- }
699
- return nil, fmt.Errorf("SyscallConn() not implemented for %T", fcpc.PacketConn)
700
-}
701
-
696
type fakeCloseQuicListener struct {
697
closed int32 // accessed atomically; belongs to this struct only
698
*sharedQuicListener // embedded, so we also become a quic.EarlyListener