github.com/metacubex/sing-tun@v0.2.7-0.20240512075008-89e7c6208eec/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  	checkUpdateTimer      *time.Timer
    47  	element               *list.Element[NetworkUpdateCallback]
    48  	access                sync.Mutex
    49  	callbacks             list.List[DefaultInterfaceUpdateCallback]
    50  	logger                logger.Logger
    51  }
    52  
    53  type networkAddress struct {
    54  	interfaceName  string
    55  	interfaceIndex int
    56  	addresses      []netip.Prefix
    57  }
    58  
    59  func NewDefaultInterfaceMonitor(networkMonitor NetworkUpdateMonitor, logger logger.Logger, options DefaultInterfaceMonitorOptions) (DefaultInterfaceMonitor, error) {
    60  	return &defaultInterfaceMonitor{
    61  		options:               options,
    62  		networkMonitor:        networkMonitor,
    63  		defaultInterfaceIndex: -1,
    64  		logger: logger,
    65  	}, nil
    66  }
    67  
    68  func (m *defaultInterfaceMonitor) Start() error {
    69  	_ = m.checkUpdate()
    70  	m.element = m.networkMonitor.RegisterCallback(m.delayCheckUpdate)
    71  	return nil
    72  }
    73  
    74  func (m *defaultInterfaceMonitor) delayCheckUpdate() {
    75  	if m.checkUpdateTimer == nil {
    76  		m.checkUpdateTimer = time.AfterFunc(time.Second, m.postCheckUpdate)
    77  	} else {
    78  		m.checkUpdateTimer.Reset(time.Second)
    79  	}
    80  }
    81  
    82  func (m *defaultInterfaceMonitor) postCheckUpdate() {
    83  	err := m.updateInterfaces()
    84  	if err != nil {
    85  		m.logger.Error("update interfaces: ", err)
    86  	}
    87  	err = m.checkUpdate()
    88  	if errors.Is(err, ErrNoRoute) {
    89  		m.defaultInterfaceName = ""
    90  		m.defaultInterfaceIndex = -1
    91  		m.emit(EventNoRoute)
    92  	} else if err != nil {
    93  		m.logger.Error("check interface: ", err)
    94  	}
    95  }
    96  
    97  func (m *defaultInterfaceMonitor) updateInterfaces() error {
    98  	interfaces, err := net.Interfaces()
    99  	if err != nil {
   100  		return err
   101  	}
   102  	var addresses []networkAddress
   103  	for _, iif := range interfaces {
   104  		var netAddresses []net.Addr
   105  		netAddresses, err = iif.Addrs()
   106  		if err != nil {
   107  			return err
   108  		}
   109  		var address networkAddress
   110  		address.interfaceName = iif.Name
   111  		address.interfaceIndex = iif.Index
   112  		address.addresses = common.Map(common.FilterIsInstance(netAddresses, func(it net.Addr) (*net.IPNet, bool) {
   113  			value, loaded := it.(*net.IPNet)
   114  			return value, loaded
   115  		}), func(it *net.IPNet) netip.Prefix {
   116  			bits, _ := it.Mask.Size()
   117  			return netip.PrefixFrom(M.AddrFromIP(it.IP), bits)
   118  		})
   119  		addresses = append(addresses, address)
   120  	}
   121  	m.networkAddresses = addresses
   122  	return nil
   123  }
   124  
   125  func (m *defaultInterfaceMonitor) Close() error {
   126  	if m.element != nil {
   127  		m.networkMonitor.UnregisterCallback(m.element)
   128  	}
   129  	return nil
   130  }
   131  
   132  func (m *defaultInterfaceMonitor) DefaultInterfaceName(destination netip.Addr) string {
   133  	for _, address := range m.networkAddresses {
   134  		for _, prefix := range address.addresses {
   135  			if prefix.Contains(destination) {
   136  				return address.interfaceName
   137  			}
   138  		}
   139  	}
   140  	return m.defaultInterfaceName
   141  }
   142  
   143  func (m *defaultInterfaceMonitor) DefaultInterfaceIndex(destination netip.Addr) int {
   144  	for _, address := range m.networkAddresses {
   145  		for _, prefix := range address.addresses {
   146  			if prefix.Contains(destination) {
   147  				return address.interfaceIndex
   148  			}
   149  		}
   150  	}
   151  	return m.defaultInterfaceIndex
   152  }
   153  
   154  func (m *defaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (string, int) {
   155  	for _, address := range m.networkAddresses {
   156  		for _, prefix := range address.addresses {
   157  			if prefix.Contains(destination) {
   158  				return address.interfaceName, address.interfaceIndex
   159  			}
   160  		}
   161  	}
   162  	return m.defaultInterfaceName, m.defaultInterfaceIndex
   163  }
   164  
   165  func (m *defaultInterfaceMonitor) OverrideAndroidVPN() bool {
   166  	return m.options.OverrideAndroidVPN
   167  }
   168  
   169  func (m *defaultInterfaceMonitor) AndroidVPNEnabled() bool {
   170  	return m.androidVPNEnabled
   171  }
   172  
   173  func (m *defaultInterfaceMonitor) RegisterCallback(callback DefaultInterfaceUpdateCallback) *list.Element[DefaultInterfaceUpdateCallback] {
   174  	m.access.Lock()
   175  	defer m.access.Unlock()
   176  	return m.callbacks.PushBack(callback)
   177  }
   178  
   179  func (m *defaultInterfaceMonitor) UnregisterCallback(element *list.Element[DefaultInterfaceUpdateCallback]) {
   180  	m.access.Lock()
   181  	defer m.access.Unlock()
   182  	m.callbacks.Remove(element)
   183  }
   184  
   185  func (m *defaultInterfaceMonitor) emit(event int) {
   186  	m.access.Lock()
   187  	callbacks := m.callbacks.Array()
   188  	m.access.Unlock()
   189  	for _, callback := range callbacks {
   190  		callback(event)
   191  	}
   192  }