package libbox import ( C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common/control" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" "github.com/sagernet/sing/common/x/list" ) var ( _ tun.DefaultInterfaceMonitor = (*platformDefaultInterfaceMonitor)(nil) _ InterfaceUpdateListener = (*platformDefaultInterfaceMonitor)(nil) ) type platformDefaultInterfaceMonitor struct { *platformInterfaceWrapper element *list.Element[tun.NetworkUpdateCallback] callbacks list.List[tun.DefaultInterfaceUpdateCallback] logger logger.Logger } func (m *platformDefaultInterfaceMonitor) Start() error { return m.iif.StartDefaultInterfaceMonitor(m) } func (m *platformDefaultInterfaceMonitor) Close() error { return m.iif.CloseDefaultInterfaceMonitor(m) } func (m *platformDefaultInterfaceMonitor) DefaultInterface() *control.Interface { m.defaultInterfaceAccess.Lock() defer m.defaultInterfaceAccess.Unlock() return m.defaultInterface } func (m *platformDefaultInterfaceMonitor) OverrideAndroidVPN() bool { return false } func (m *platformDefaultInterfaceMonitor) AndroidVPNEnabled() bool { return false } func (m *platformDefaultInterfaceMonitor) RegisterCallback(callback tun.DefaultInterfaceUpdateCallback) *list.Element[tun.DefaultInterfaceUpdateCallback] { m.defaultInterfaceAccess.Lock() defer m.defaultInterfaceAccess.Unlock() return m.callbacks.PushBack(callback) } func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) { m.defaultInterfaceAccess.Lock() defer m.defaultInterfaceAccess.Unlock() m.callbacks.Remove(element) } func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32, isExpensive bool, isConstrained bool) { if C.FixAndroidStack { go m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained) } else { m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained) } } func (m *platformDefaultInterfaceMonitor) updateDefaultInterface(interfaceName string, interfaceIndex32 int32, isExpensive bool, isConstrained bool) { m.isExpensive = isExpensive m.isConstrained = isConstrained err := m.networkManager.UpdateInterfaces() if err != nil { m.logger.Error(E.Cause(err, "update interfaces")) } m.defaultInterfaceAccess.Lock() if interfaceIndex32 == -1 { m.defaultInterface = nil callbacks := m.callbacks.Array() m.defaultInterfaceAccess.Unlock() for _, callback := range callbacks { callback(tun.EventInterfaceUpdate) } return } oldInterface := m.defaultInterface newInterface, err := m.networkManager.InterfaceFinder().ByIndex(int(interfaceIndex32)) if err != nil { m.defaultInterfaceAccess.Unlock() m.logger.Error(E.Cause(err, "find updated interface: ", interfaceName)) return } m.defaultInterface = newInterface if oldInterface != nil && oldInterface.Name == m.defaultInterface.Name && oldInterface.Index == m.defaultInterface.Index { m.defaultInterfaceAccess.Unlock() return } callbacks := m.callbacks.Array() m.defaultInterfaceAccess.Unlock() for _, callback := range callbacks { callback(tun.EventInterfaceUpdate) } }