github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/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.Stop()
    77  	}
    78  	m.checkUpdateTimer = time.AfterFunc(time.Second, m.postCheckUpdate)
    79  }
    80  
    81  func (m *defaultInterfaceMonitor) postCheckUpdate() {
    82  	err := m.updateInterfaces()
    83  	if err != nil {
    84  		m.logger.Error("update interfaces: ", err)
    85  	}
    86  	err = m.checkUpdate()
    87  	if errors.Is(err, ErrNoRoute) {
    88  		m.defaultInterfaceName = ""
    89  		m.defaultInterfaceIndex = -1
    90  		m.emit(EventNoRoute)
    91  	} else if err != nil {
    92  		m.logger.Error("check interface: ", err)
    93  	}
    94  }
    95  
    96  func (m *defaultInterfaceMonitor) updateInterfaces() error {
    97  	interfaces, err := net.Interfaces()
    98  	if err != nil {
    99  		return err
   100  	}
   101  	var addresses []networkAddress
   102  	for _, iif := range interfaces {
   103  		var netAddresses []net.Addr
   104  		netAddresses, err = iif.Addrs()
   105  		if err != nil {
   106  			return err
   107  		}
   108  		var address networkAddress
   109  		address.interfaceName = iif.Name
   110  		address.interfaceIndex = iif.Index
   111  		address.addresses = common.Map(common.FilterIsInstance(netAddresses, func(it net.Addr) (*net.IPNet, bool) {
   112  			value, loaded := it.(*net.IPNet)
   113  			return value, loaded
   114  		}), func(it *net.IPNet) netip.Prefix {
   115  			bits, _ := it.Mask.Size()
   116  			return netip.PrefixFrom(M.AddrFromIP(it.IP), bits)
   117  		})
   118  		addresses = append(addresses, address)
   119  	}
   120  	m.networkAddresses = addresses
   121  	return nil
   122  }
   123  
   124  func (m *defaultInterfaceMonitor) Close() error {
   125  	if m.element != nil {
   126  		m.networkMonitor.UnregisterCallback(m.element)
   127  	}
   128  	return nil
   129  }
   130  
   131  func (m *defaultInterfaceMonitor) DefaultInterfaceName(destination netip.Addr) string {
   132  	for _, address := range m.networkAddresses {
   133  		for _, prefix := range address.addresses {
   134  			if prefix.Contains(destination) {
   135  				return address.interfaceName
   136  			}
   137  		}
   138  	}
   139  	return m.defaultInterfaceName
   140  }
   141  
   142  func (m *defaultInterfaceMonitor) DefaultInterfaceIndex(destination netip.Addr) int {
   143  	for _, address := range m.networkAddresses {
   144  		for _, prefix := range address.addresses {
   145  			if prefix.Contains(destination) {
   146  				return address.interfaceIndex
   147  			}
   148  		}
   149  	}
   150  	return m.defaultInterfaceIndex
   151  }
   152  
   153  func (m *defaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (string, int) {
   154  	for _, address := range m.networkAddresses {
   155  		for _, prefix := range address.addresses {
   156  			if prefix.Contains(destination) {
   157  				return address.interfaceName, address.interfaceIndex
   158  			}
   159  		}
   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  }