gin/listener.go
2026-04-21 19:45:17 +08:00

48 lines
1.1 KiB
Go

// Copyright 2025 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package gin
import (
"net"
"sync"
)
// limitedListener wraps a net.Listener and limits the number of concurrent connections
// using a buffered channel as a semaphore.
type limitedListener struct {
net.Listener
sem chan struct{}
}
// Accept accepts a new connection. If the connection limit has been reached,
// the new connection is immediately closed.
func (l *limitedListener) Accept() (net.Conn, error) {
conn, err := l.Listener.Accept()
if err != nil {
return nil, err
}
select {
case l.sem <- struct{}{}:
return &limitedConn{Conn: conn, sem: l.sem}, nil
default:
conn.Close()
return nil, nil
}
}
// limitedConn wraps a net.Conn and releases the semaphore slot on Close.
type limitedConn struct {
net.Conn
sem chan struct{}
closeOnce sync.Once
}
// Close closes the connection and releases the semaphore slot.
func (c *limitedConn) Close() error {
c.closeOnce.Do(func() { <-c.sem })
return c.Conn.Close()
}