mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-09-26 20:51:13 +08:00
62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
package tun
|
|
|
|
import (
|
|
"net/netip"
|
|
"time"
|
|
|
|
"github.com/sagernet/sing/common"
|
|
"github.com/sagernet/sing/common/buf"
|
|
"github.com/sagernet/sing/contrab/freelru"
|
|
"github.com/sagernet/sing/contrab/maphash"
|
|
)
|
|
|
|
type DirectRouteDestination interface {
|
|
WritePacket(packet *buf.Buffer) error
|
|
Close() error
|
|
IsClosed() bool
|
|
}
|
|
|
|
type DirectRouteSession struct {
|
|
// IPVersion uint8
|
|
// Network uint8
|
|
Source netip.Addr
|
|
Destination netip.Addr
|
|
}
|
|
|
|
type DirectRouteMapping struct {
|
|
mapping freelru.Cache[DirectRouteSession, DirectRouteDestination]
|
|
timeout time.Duration
|
|
}
|
|
|
|
func NewDirectRouteMapping(timeout time.Duration) *DirectRouteMapping {
|
|
mapping := common.Must1(freelru.NewSharded[DirectRouteSession, DirectRouteDestination](1024, maphash.NewHasher[DirectRouteSession]().Hash32))
|
|
mapping.SetHealthCheck(func(session DirectRouteSession, action DirectRouteDestination) bool {
|
|
if action != nil {
|
|
return !action.IsClosed()
|
|
}
|
|
return true
|
|
})
|
|
mapping.SetOnEvict(func(session DirectRouteSession, action DirectRouteDestination) {
|
|
if action != nil {
|
|
action.Close()
|
|
}
|
|
})
|
|
mapping.SetLifetime(timeout)
|
|
return &DirectRouteMapping{mapping, timeout}
|
|
}
|
|
|
|
func (m *DirectRouteMapping) Lookup(session DirectRouteSession, constructor func(timeout time.Duration) (DirectRouteDestination, error)) (DirectRouteDestination, error) {
|
|
var (
|
|
created DirectRouteDestination
|
|
err error
|
|
)
|
|
action, _, ok := m.mapping.GetAndRefreshOrAdd(session, func() (DirectRouteDestination, bool) {
|
|
created, err = constructor(m.timeout)
|
|
return created, err == nil
|
|
})
|
|
if !ok {
|
|
return nil, err
|
|
}
|
|
return action, nil
|
|
}
|