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  }