github.com/sagernet/sing-box@v1.9.0-rc.20/common/interrupt/group.go (about) 1 package interrupt 2 3 import ( 4 "io" 5 "net" 6 "sync" 7 8 "github.com/sagernet/sing/common/x/list" 9 ) 10 11 type Group struct { 12 access sync.Mutex 13 connections list.List[*groupConnItem] 14 } 15 16 type groupConnItem struct { 17 conn io.Closer 18 isExternal bool 19 } 20 21 func NewGroup() *Group { 22 return &Group{} 23 } 24 25 func (g *Group) NewConn(conn net.Conn, isExternal bool) net.Conn { 26 g.access.Lock() 27 defer g.access.Unlock() 28 item := g.connections.PushBack(&groupConnItem{conn, isExternal}) 29 return &Conn{Conn: conn, group: g, element: item} 30 } 31 32 func (g *Group) NewPacketConn(conn net.PacketConn, isExternal bool) net.PacketConn { 33 g.access.Lock() 34 defer g.access.Unlock() 35 item := g.connections.PushBack(&groupConnItem{conn, isExternal}) 36 return &PacketConn{PacketConn: conn, group: g, element: item} 37 } 38 39 func (g *Group) Interrupt(interruptExternalConnections bool) { 40 g.access.Lock() 41 defer g.access.Unlock() 42 var toDelete []*list.Element[*groupConnItem] 43 for element := g.connections.Front(); element != nil; element = element.Next() { 44 if !element.Value.isExternal || interruptExternalConnections { 45 element.Value.conn.Close() 46 toDelete = append(toDelete, element) 47 } 48 } 49 for _, element := range toDelete { 50 g.connections.Remove(element) 51 } 52 }