2019-10-11 20:11:18 +08:00
|
|
|
package nat
|
|
|
|
|
|
|
|
import (
|
2023-02-17 16:31:15 +08:00
|
|
|
"net"
|
2019-10-11 20:11:18 +08:00
|
|
|
"sync"
|
2020-02-17 17:34:19 +08:00
|
|
|
|
2023-11-03 21:01:45 +08:00
|
|
|
C "github.com/metacubex/mihomo/constant"
|
2023-09-02 16:54:35 +08:00
|
|
|
|
2023-11-23 10:24:01 +08:00
|
|
|
"github.com/puzpuzpuz/xsync/v3"
|
2019-10-11 20:11:18 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type Table struct {
|
2024-09-26 11:21:07 +08:00
|
|
|
mapping *xsync.MapOf[string, *entry]
|
2019-10-11 20:11:18 +08:00
|
|
|
}
|
|
|
|
|
2024-09-26 11:21:07 +08:00
|
|
|
type entry struct {
|
|
|
|
PacketSender C.PacketSender
|
2023-09-02 16:54:35 +08:00
|
|
|
LocalUDPConnMap *xsync.MapOf[string, *net.UDPConn]
|
|
|
|
LocalLockMap *xsync.MapOf[string, *sync.Cond]
|
2023-02-17 16:31:15 +08:00
|
|
|
}
|
|
|
|
|
2024-09-26 11:21:07 +08:00
|
|
|
func (t *Table) GetOrCreate(key string, maker func() C.PacketSender) (C.PacketSender, bool) {
|
|
|
|
item, loaded := t.mapping.LoadOrCompute(key, func() *entry {
|
|
|
|
return &entry{
|
|
|
|
PacketSender: maker(),
|
|
|
|
LocalUDPConnMap: xsync.NewMapOf[string, *net.UDPConn](),
|
|
|
|
LocalLockMap: xsync.NewMapOf[string, *sync.Cond](),
|
|
|
|
}
|
2023-02-17 16:31:15 +08:00
|
|
|
})
|
2024-09-26 11:21:07 +08:00
|
|
|
return item.PacketSender, loaded
|
2019-10-11 20:11:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Table) Delete(key string) {
|
|
|
|
t.mapping.Delete(key)
|
|
|
|
}
|
|
|
|
|
2023-09-02 16:54:35 +08:00
|
|
|
func (t *Table) GetForLocalConn(lAddr, rAddr string) *net.UDPConn {
|
2023-02-17 16:31:15 +08:00
|
|
|
entry, exist := t.getEntry(lAddr)
|
|
|
|
if !exist {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
item, exist := entry.LocalUDPConnMap.Load(rAddr)
|
|
|
|
if !exist {
|
|
|
|
return nil
|
|
|
|
}
|
2023-09-02 16:54:35 +08:00
|
|
|
return item
|
2023-02-17 16:31:15 +08:00
|
|
|
}
|
|
|
|
|
2023-09-02 16:54:35 +08:00
|
|
|
func (t *Table) AddForLocalConn(lAddr, rAddr string, conn *net.UDPConn) bool {
|
2023-02-17 16:31:15 +08:00
|
|
|
entry, exist := t.getEntry(lAddr)
|
|
|
|
if !exist {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
entry.LocalUDPConnMap.Store(rAddr, conn)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-09-02 16:54:35 +08:00
|
|
|
func (t *Table) RangeForLocalConn(lAddr string, f func(key string, value *net.UDPConn) bool) {
|
2023-02-17 16:31:15 +08:00
|
|
|
entry, exist := t.getEntry(lAddr)
|
|
|
|
if !exist {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
entry.LocalUDPConnMap.Range(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Table) GetOrCreateLockForLocalConn(lAddr, key string) (*sync.Cond, bool) {
|
|
|
|
entry, loaded := t.getEntry(lAddr)
|
|
|
|
if !loaded {
|
|
|
|
return nil, false
|
|
|
|
}
|
2023-09-02 16:54:35 +08:00
|
|
|
item, loaded := entry.LocalLockMap.LoadOrCompute(key, makeLock)
|
|
|
|
return item, loaded
|
2023-02-17 16:31:15 +08:00
|
|
|
}
|
|
|
|
|
2023-09-02 16:54:35 +08:00
|
|
|
func (t *Table) DeleteForLocalConn(lAddr, key string) {
|
2023-02-17 16:31:15 +08:00
|
|
|
entry, loaded := t.getEntry(lAddr)
|
|
|
|
if !loaded {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
entry.LocalUDPConnMap.Delete(key)
|
|
|
|
}
|
|
|
|
|
2023-09-02 16:54:35 +08:00
|
|
|
func (t *Table) DeleteLockForLocalConn(lAddr, key string) {
|
|
|
|
entry, loaded := t.getEntry(lAddr)
|
|
|
|
if !loaded {
|
|
|
|
return
|
2023-02-17 16:31:15 +08:00
|
|
|
}
|
2023-09-02 16:54:35 +08:00
|
|
|
entry.LocalLockMap.Delete(key)
|
|
|
|
}
|
|
|
|
|
2024-09-26 11:21:07 +08:00
|
|
|
func (t *Table) getEntry(key string) (*entry, bool) {
|
2023-09-02 16:54:35 +08:00
|
|
|
return t.mapping.Load(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeLock() *sync.Cond {
|
|
|
|
return sync.NewCond(&sync.Mutex{})
|
2023-02-17 16:31:15 +08:00
|
|
|
}
|
|
|
|
|
2019-10-11 20:11:18 +08:00
|
|
|
// New return *Cache
|
|
|
|
func New() *Table {
|
2023-09-02 16:54:35 +08:00
|
|
|
return &Table{
|
2024-09-26 11:21:07 +08:00
|
|
|
mapping: xsync.NewMapOf[string, *entry](),
|
2023-09-02 16:54:35 +08:00
|
|
|
}
|
2019-10-11 20:11:18 +08:00
|
|
|
}
|