package interrupt import ( "io" "net" "sync" "github.com/sagernet/sing/common/x/list" ) type Group struct { access sync.Mutex connections list.List[*groupConnItem] } type groupConnItem struct { conn io.Closer isExternal bool } func NewGroup() *Group { return &Group{} } func (g *Group) NewConn(conn net.Conn, isExternal bool) net.Conn { g.access.Lock() defer g.access.Unlock() item := g.connections.PushBack(&groupConnItem{conn, isExternal}) return &Conn{Conn: conn, group: g, element: item} } func (g *Group) NewPacketConn(conn net.PacketConn, isExternal bool) net.PacketConn { g.access.Lock() defer g.access.Unlock() item := g.connections.PushBack(&groupConnItem{conn, isExternal}) return &PacketConn{PacketConn: conn, group: g, element: item} } func (g *Group) Interrupt(interruptExternalConnections bool) { g.access.Lock() defer g.access.Unlock() var toDelete []*list.Element[*groupConnItem] for element := g.connections.Front(); element != nil; element = element.Next() { if !element.Value.isExternal || interruptExternalConnections { element.Value.conn.Close() toDelete = append(toDelete, element) } } for _, element := range toDelete { g.connections.Remove(element) } }