Repository: caddyserver/caddy
File: listeners.go (Go)

Code before:
	if uc, ok := ln.(*unixConn); ok {
		unix = uc
	}

	return &fakeCloseQuicListener{
		sharedQuicListener: sql,
		uc:                 unix,
		context:            ctx,
		contextCancel:      cancel,
	}, nil
}

// ListenerUsage returns the current usage count of the given listener address.
func ListenerUsage(network, addr string) int {
	count, _ := listenerPool.References(listenerKey(network, addr))
	return count
}

// contextAndCancelFunc groups context and its cancelFunc
type contextAndCancelFunc struct {
	context.Context
	context.CancelFunc
}

// sharedQuicTlsConfig manages GetConfigForClient
type sharedQuicTlsConfig struct {
	rmu           sync.RWMutex
	tlsConfs      map[*tls.Config]contextAndCancelFunc
	activeTlsConf *tls.Config
}

// newSqtc creates a new sharedQuicTlsConfig
func newSqtc(tlsConfig *tls.Config) *sharedQuicTlsConfig {
	sqtc := &sharedQuicTlsConfig{
		tlsConfs:      make(map[*tls.Config]contextAndCancelFunc),
		activeTlsConf: tlsConfig,
	}
	sqtc.addTlsConfig(tlsConfig)
	return sqtc
}

func (sqtc *sharedQuicTlsConfig) getConfigForClient(ch *tls.ClientHelloInfo) (*tls.Config, error) {
	sqtc.rmu.RLock()
	defer sqtc.rmu.RUnlock()
	return sqtc.activeTlsConf.GetConfigForClient(ch)
}

func (sqtc *sharedQuicTlsConfig) addTlsConfig(tlsConfig *tls.Config) (context.Context, context.CancelFunc) {
	sqtc.rmu.Lock()
	defer sqtc.rmu.Unlock()


Review comment (suggestion):
```suggestion
type sharedQUICTLSConfig struct {
```

Code after:
	// add current tls.Config to sqtc, so GetConfigForClient will always return the latest tls.Config in case of context cancellation
	ctx, cancel := sql.sqtc.addTLSConfig(tlsConf)

	// TODO: to serve QUIC over a unix socket, currently we need to hold onto
	// the underlying net.PacketConn (which we wrap as unixConn to keep count
	// of closes) because closing the quic.EarlyListener doesn't actually close
	// the underlying PacketConn, but we need to for unix sockets since we dup
	// the file descriptor and thus need to close the original; track issue:
	// https://github.com/quic-go/quic-go/issues/3560#issuecomment-1258959608
	var unix *unixConn
	if uc, ok := ln.(*unixConn); ok {
		unix = uc
	}

	return &fakeCloseQuicListener{
		sharedQuicListener: sql,
		uc:                 unix,
		context:            ctx,
		contextCancel:      cancel,
	}, nil
}

// ListenerUsage returns the current usage count of the given listener address.
func ListenerUsage(network, addr string) int {
	count, _ := listenerPool.References(listenerKey(network, addr))
	return count
}

// contextAndCancelFunc groups context and its cancelFunc
type contextAndCancelFunc struct {
	context.Context
	context.CancelFunc
}

// sharedQUICTLSConfig manages GetConfigForClient
// see issue: https://github.com/caddyserver/caddy/pull/4849
type sharedQUICTLSConfig struct {
	rmu           sync.RWMutex
	tlsConfs      map[*tls.Config]contextAndCancelFunc
	activeTlsConf *tls.Config
}

// newSharedQUICTLSConfig creates a new sharedQUICTLSConfig
func newSharedQUICTLSConfig(tlsConfig *tls.Config) *sharedQUICTLSConfig {
	sqtc := &sharedQUICTLSConfig{
		tlsConfs:      make(map[*tls.Config]contextAndCancelFunc),
		activeTlsConf: tlsConfig,
	}
	sqtc.addTLSConfig(tlsConfig)
	return sqtc
}