github.com/MerlinKodo/sing-tun@v0.1.15/monitor_shared.go (about) 1 //go:build linux || windows || darwin 2 3 package tun 4 5 import ( 6 "errors" 7 "net" 8 "net/netip" 9 "sync" 10 "time" 11 12 "github.com/sagernet/sing/common" 13 "github.com/sagernet/sing/common/logger" 14 M "github.com/sagernet/sing/common/metadata" 15 "github.com/sagernet/sing/common/x/list" 16 ) 17 18 func (m *networkUpdateMonitor) RegisterCallback(callback NetworkUpdateCallback) *list.Element[NetworkUpdateCallback] { 19 m.access.Lock() 20 defer m.access.Unlock() 21 return m.callbacks.PushBack(callback) 22 } 23 24 func (m *networkUpdateMonitor) UnregisterCallback(element *list.Element[NetworkUpdateCallback]) { 25 m.access.Lock() 26 defer m.access.Unlock() 27 m.callbacks.Remove(element) 28 } 29 30 func (m *networkUpdateMonitor) emit() { 31 m.access.Lock() 32 callbacks := m.callbacks.Array() 33 m.access.Unlock() 34 for _, callback := range callbacks { 35 callback() 36 } 37 } 38 39 type defaultInterfaceMonitor struct { 40 options DefaultInterfaceMonitorOptions 41 networkAddresses []networkAddress 42 defaultInterfaceName string 43 defaultInterfaceIndex int 44 androidVPNEnabled bool 45 networkMonitor NetworkUpdateMonitor 46 element *list.Element[NetworkUpdateCallback] 47 access sync.Mutex 48 callbacks list.List[DefaultInterfaceUpdateCallback] 49 logger logger.Logger 50 } 51 52 type networkAddress struct { 53 interfaceName string 54 interfaceIndex int 55 addresses []netip.Prefix 56 } 57 58 func NewDefaultInterfaceMonitor(networkMonitor NetworkUpdateMonitor, logger logger.Logger, options DefaultInterfaceMonitorOptions) (DefaultInterfaceMonitor, error) { 59 return &defaultInterfaceMonitor{ 60 options: options, 61 networkMonitor: networkMonitor, 62 defaultInterfaceIndex: -1, 63 logger: logger, 64 }, nil 65 } 66 67 func (m *defaultInterfaceMonitor) Start() error { 68 _ = m.checkUpdate() 69 m.element = m.networkMonitor.RegisterCallback(m.delayCheckUpdate) 70 return nil 71 } 72 73 func (m *defaultInterfaceMonitor) delayCheckUpdate() { 74 time.Sleep(time.Second) 75 err := m.updateInterfaces() 76 if err != nil { 77 m.logger.Error("update interfaces: ", err) 78 } 79 err = m.checkUpdate() 80 if errors.Is(err, ErrNoRoute) { 81 m.defaultInterfaceName = "" 82 m.defaultInterfaceIndex = -1 83 m.emit(EventNoRoute) 84 } 85 } 86 87 func (m *defaultInterfaceMonitor) updateInterfaces() error { 88 interfaces, err := net.Interfaces() 89 if err != nil { 90 return err 91 } 92 var addresses []networkAddress 93 for _, iif := range interfaces { 94 var netAddresses []net.Addr 95 netAddresses, err = iif.Addrs() 96 if err != nil { 97 return err 98 } 99 var address networkAddress 100 address.interfaceName = iif.Name 101 address.interfaceIndex = iif.Index 102 address.addresses = common.Map(common.FilterIsInstance(netAddresses, func(it net.Addr) (*net.IPNet, bool) { 103 value, loaded := it.(*net.IPNet) 104 return value, loaded 105 }), func(it *net.IPNet) netip.Prefix { 106 bits, _ := it.Mask.Size() 107 return netip.PrefixFrom(M.AddrFromIP(it.IP), bits) 108 }) 109 addresses = append(addresses, address) 110 } 111 m.networkAddresses = addresses 112 return nil 113 } 114 115 func (m *defaultInterfaceMonitor) Close() error { 116 if m.element != nil { 117 m.networkMonitor.UnregisterCallback(m.element) 118 } 119 return nil 120 } 121 122 func (m *defaultInterfaceMonitor) DefaultInterfaceName(destination netip.Addr) string { 123 for _, address := range m.networkAddresses { 124 for _, prefix := range address.addresses { 125 if prefix.Contains(destination) { 126 return address.interfaceName 127 } 128 } 129 } 130 if m.defaultInterfaceIndex == -1 { 131 m.checkUpdate() 132 } 133 return m.defaultInterfaceName 134 } 135 136 func (m *defaultInterfaceMonitor) DefaultInterfaceIndex(destination netip.Addr) int { 137 for _, address := range m.networkAddresses { 138 for _, prefix := range address.addresses { 139 if prefix.Contains(destination) { 140 return address.interfaceIndex 141 } 142 } 143 } 144 if m.defaultInterfaceIndex == -1 { 145 m.checkUpdate() 146 } 147 return m.defaultInterfaceIndex 148 } 149 150 func (m *defaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (string, int) { 151 for _, address := range m.networkAddresses { 152 for _, prefix := range address.addresses { 153 if prefix.Contains(destination) { 154 return address.interfaceName, address.interfaceIndex 155 } 156 } 157 } 158 if m.defaultInterfaceIndex == -1 { 159 m.checkUpdate() 160 } 161 return m.defaultInterfaceName, m.defaultInterfaceIndex 162 } 163 164 func (m *defaultInterfaceMonitor) OverrideAndroidVPN() bool { 165 return m.options.OverrideAndroidVPN 166 } 167 168 func (m *defaultInterfaceMonitor) AndroidVPNEnabled() bool { 169 return m.androidVPNEnabled 170 } 171 172 func (m *defaultInterfaceMonitor) RegisterCallback(callback DefaultInterfaceUpdateCallback) *list.Element[DefaultInterfaceUpdateCallback] { 173 m.access.Lock() 174 defer m.access.Unlock() 175 return m.callbacks.PushBack(callback) 176 } 177 178 func (m *defaultInterfaceMonitor) UnregisterCallback(element *list.Element[DefaultInterfaceUpdateCallback]) { 179 m.access.Lock() 180 defer m.access.Unlock() 181 m.callbacks.Remove(element) 182 } 183 184 func (m *defaultInterfaceMonitor) emit(event int) { 185 m.access.Lock() 186 callbacks := m.callbacks.Array() 187 m.access.Unlock() 188 for _, callback := range callbacks { 189 callback(event) 190 } 191 }