github.com/kelleygo/clashcore@v1.0.2/component/nat/table.go (about)

     1  package nat
     2  
     3  import (
     4  	"net"
     5  	"sync"
     6  
     7  	C "github.com/kelleygo/clashcore/constant"
     8  
     9  	"github.com/puzpuzpuz/xsync/v3"
    10  )
    11  
    12  type Table struct {
    13  	mapping *xsync.MapOf[string, *Entry]
    14  	lockMap *xsync.MapOf[string, *sync.Cond]
    15  }
    16  
    17  type Entry struct {
    18  	PacketConn      C.PacketConn
    19  	WriteBackProxy  C.WriteBackProxy
    20  	LocalUDPConnMap *xsync.MapOf[string, *net.UDPConn]
    21  	LocalLockMap    *xsync.MapOf[string, *sync.Cond]
    22  }
    23  
    24  func (t *Table) Set(key string, e C.PacketConn, w C.WriteBackProxy) {
    25  	t.mapping.Store(key, &Entry{
    26  		PacketConn:      e,
    27  		WriteBackProxy:  w,
    28  		LocalUDPConnMap: xsync.NewMapOf[string, *net.UDPConn](),
    29  		LocalLockMap:    xsync.NewMapOf[string, *sync.Cond](),
    30  	})
    31  }
    32  
    33  func (t *Table) Get(key string) (C.PacketConn, C.WriteBackProxy) {
    34  	entry, exist := t.getEntry(key)
    35  	if !exist {
    36  		return nil, nil
    37  	}
    38  	return entry.PacketConn, entry.WriteBackProxy
    39  }
    40  
    41  func (t *Table) GetOrCreateLock(key string) (*sync.Cond, bool) {
    42  	item, loaded := t.lockMap.LoadOrCompute(key, makeLock)
    43  	return item, loaded
    44  }
    45  
    46  func (t *Table) Delete(key string) {
    47  	t.mapping.Delete(key)
    48  }
    49  
    50  func (t *Table) DeleteLock(lockKey string) {
    51  	t.lockMap.Delete(lockKey)
    52  }
    53  
    54  func (t *Table) GetForLocalConn(lAddr, rAddr string) *net.UDPConn {
    55  	entry, exist := t.getEntry(lAddr)
    56  	if !exist {
    57  		return nil
    58  	}
    59  	item, exist := entry.LocalUDPConnMap.Load(rAddr)
    60  	if !exist {
    61  		return nil
    62  	}
    63  	return item
    64  }
    65  
    66  func (t *Table) AddForLocalConn(lAddr, rAddr string, conn *net.UDPConn) bool {
    67  	entry, exist := t.getEntry(lAddr)
    68  	if !exist {
    69  		return false
    70  	}
    71  	entry.LocalUDPConnMap.Store(rAddr, conn)
    72  	return true
    73  }
    74  
    75  func (t *Table) RangeForLocalConn(lAddr string, f func(key string, value *net.UDPConn) bool) {
    76  	entry, exist := t.getEntry(lAddr)
    77  	if !exist {
    78  		return
    79  	}
    80  	entry.LocalUDPConnMap.Range(f)
    81  }
    82  
    83  func (t *Table) GetOrCreateLockForLocalConn(lAddr, key string) (*sync.Cond, bool) {
    84  	entry, loaded := t.getEntry(lAddr)
    85  	if !loaded {
    86  		return nil, false
    87  	}
    88  	item, loaded := entry.LocalLockMap.LoadOrCompute(key, makeLock)
    89  	return item, loaded
    90  }
    91  
    92  func (t *Table) DeleteForLocalConn(lAddr, key string) {
    93  	entry, loaded := t.getEntry(lAddr)
    94  	if !loaded {
    95  		return
    96  	}
    97  	entry.LocalUDPConnMap.Delete(key)
    98  }
    99  
   100  func (t *Table) DeleteLockForLocalConn(lAddr, key string) {
   101  	entry, loaded := t.getEntry(lAddr)
   102  	if !loaded {
   103  		return
   104  	}
   105  	entry.LocalLockMap.Delete(key)
   106  }
   107  
   108  func (t *Table) getEntry(key string) (*Entry, bool) {
   109  	return t.mapping.Load(key)
   110  }
   111  
   112  func makeLock() *sync.Cond {
   113  	return sync.NewCond(&sync.Mutex{})
   114  }
   115  
   116  // New return *Cache
   117  func New() *Table {
   118  	return &Table{
   119  		mapping: xsync.NewMapOf[string, *Entry](),
   120  		lockMap: xsync.NewMapOf[string, *sync.Cond](),
   121  	}
   122  }