Files
sing-box-extended-mirror/route/network_environment.go
T
2026-08-30 17:41:46 +08:00

101 lines
2.7 KiB
Go

package route
import (
"hash/fnv"
"net/netip"
"slices"
"strings"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common"
)
func (r *NetworkManager) NetworkEnvironment() uint64 {
r.stateAccess.RLock()
defer r.stateAccess.RUnlock()
return r.networkEnvironment
}
func (r *NetworkManager) postUpdateNetworkEnvironment() {
r.environmentUpdateAccess.Lock()
defer r.environmentUpdateAccess.Unlock()
if r.environmentUpdateTimer == nil {
r.environmentUpdateTimer = time.AfterFunc(time.Second, r.updateNetworkEnvironment)
} else {
r.environmentUpdateTimer.Reset(time.Second)
}
}
func (r *NetworkManager) updateNetworkEnvironment() {
r.environmentUpdateAccess.Lock()
defer r.environmentUpdateAccess.Unlock()
if r.environmentUpdateTimer != nil {
r.environmentUpdateTimer.Stop()
}
var defaultInterface *adapter.NetworkInterface
if r.interfaceMonitor != nil {
defaultInterface = r.DefaultNetworkInterface()
}
var (
gatewayStrings []string
hardwareStrings []string
wifiSSID string
)
if defaultInterface != nil {
gateways := defaultInterface.Gateways
if len(gateways) == 0 {
gateways = systemGateways(defaultInterface.Interface.Index)
}
gateways = common.Uniq(gateways)
slices.SortFunc(gateways, netip.Addr.Compare)
gatewayStrings = common.Map(gateways, netip.Addr.String)
wifiState := r.WIFIState()
if wifiState.SSID != "" {
wifiSSID = wifiState.SSID
} else if len(gateways) > 0 {
hardwareAddresses := systemNeighborHardwareAddresses(defaultInterface.Interface.Index, gateways)
for _, gateway := range gateways {
hardwareAddress := hardwareAddresses[gateway]
if len(hardwareAddress) > 0 {
hardwareStrings = append(hardwareStrings, hardwareAddress.String())
}
}
}
}
var options []string
if len(gatewayStrings) > 0 {
options = append(options, "gateway "+formatEnvironmentValues(gatewayStrings))
}
if wifiSSID != "" {
options = append(options, "ssid "+wifiSSID)
}
if len(hardwareStrings) > 0 {
options = append(options, "gateway_mac "+formatEnvironmentValues(hardwareStrings))
}
var environmentHash uint64
if len(options) > 0 {
digest := fnv.New64a()
for _, option := range options {
digest.Write([]byte(option))
digest.Write([]byte{0})
}
environmentHash = digest.Sum64()
}
r.stateAccess.Lock()
changed := environmentHash != r.networkEnvironment
r.networkEnvironment = environmentHash
r.stateAccess.Unlock()
if !changed || len(options) == 0 {
return
}
r.logger.Info("updated network environment: ", strings.Join(options, ", "))
}
func formatEnvironmentValues(values []string) string {
if len(values) == 1 {
return values[0]
}
return "[" + strings.Join(values, " ") + "]"
}