github.com/sagernet/sing-box@v1.2.7/experimental/libbox/service.go (about)

     1  package libbox
     2  
     3  import (
     4  	"context"
     5  	"net/netip"
     6  	"syscall"
     7  
     8  	"github.com/sagernet/sing-box"
     9  	"github.com/sagernet/sing-box/adapter"
    10  	"github.com/sagernet/sing-box/common/process"
    11  	"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
    12  	"github.com/sagernet/sing-box/experimental/libbox/platform"
    13  	"github.com/sagernet/sing-box/option"
    14  	"github.com/sagernet/sing-tun"
    15  	"github.com/sagernet/sing/common"
    16  	"github.com/sagernet/sing/common/control"
    17  	E "github.com/sagernet/sing/common/exceptions"
    18  	N "github.com/sagernet/sing/common/network"
    19  )
    20  
    21  type BoxService struct {
    22  	ctx      context.Context
    23  	cancel   context.CancelFunc
    24  	instance *box.Box
    25  }
    26  
    27  func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
    28  	options, err := parseConfig(configContent)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	ctx, cancel := context.WithCancel(context.Background())
    33  	instance, err := box.New(box.Options{
    34  		Context:           ctx,
    35  		Options:           options,
    36  		PlatformInterface: &platformInterfaceWrapper{iif: platformInterface, useProcFS: platformInterface.UseProcFS()},
    37  	})
    38  	if err != nil {
    39  		cancel()
    40  		return nil, E.Cause(err, "create service")
    41  	}
    42  	return &BoxService{
    43  		ctx:      ctx,
    44  		cancel:   cancel,
    45  		instance: instance,
    46  	}, nil
    47  }
    48  
    49  func (s *BoxService) Start() error {
    50  	return s.instance.Start()
    51  }
    52  
    53  func (s *BoxService) Close() error {
    54  	s.cancel()
    55  	return s.instance.Close()
    56  }
    57  
    58  var _ platform.Interface = (*platformInterfaceWrapper)(nil)
    59  
    60  type platformInterfaceWrapper struct {
    61  	iif       PlatformInterface
    62  	useProcFS bool
    63  	router    adapter.Router
    64  }
    65  
    66  func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error {
    67  	w.router = router
    68  	return nil
    69  }
    70  
    71  func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
    72  	return w.iif.UsePlatformAutoDetectInterfaceControl()
    73  }
    74  
    75  func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
    76  	return func(network, address string, conn syscall.RawConn) error {
    77  		return control.Raw(conn, func(fd uintptr) error {
    78  			return w.iif.AutoDetectInterfaceControl(int32(fd))
    79  		})
    80  	}
    81  }
    82  
    83  func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
    84  	if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
    85  		return nil, E.New("android: unsupported uid options")
    86  	}
    87  	if len(options.IncludeAndroidUser) > 0 {
    88  		return nil, E.New("android: unsupported android_user option")
    89  	}
    90  	tunFd, err := w.iif.OpenTun(&tunOptions{options, platformOptions})
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	options.Name, err = getTunnelName(tunFd)
    95  	if err != nil {
    96  		return nil, E.Cause(err, "query tun name")
    97  	}
    98  	dupFd, err := dup(int(tunFd))
    99  	if err != nil {
   100  		return nil, E.Cause(err, "dup tun file descriptor")
   101  	}
   102  	options.FileDescriptor = dupFd
   103  	return tun.New(*options)
   104  }
   105  
   106  func (w *platformInterfaceWrapper) Write(p []byte) (n int, err error) {
   107  	w.iif.WriteLog(string(p))
   108  	return len(p), nil
   109  }
   110  
   111  func (w *platformInterfaceWrapper) FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*process.Info, error) {
   112  	var uid int32
   113  	if w.useProcFS {
   114  		uid = procfs.ResolveSocketByProcSearch(network, source, destination)
   115  		if uid == -1 {
   116  			return nil, E.New("procfs: not found")
   117  		}
   118  	} else {
   119  		var ipProtocol int32
   120  		switch N.NetworkName(network) {
   121  		case N.NetworkTCP:
   122  			ipProtocol = syscall.IPPROTO_TCP
   123  		case N.NetworkUDP:
   124  			ipProtocol = syscall.IPPROTO_UDP
   125  		default:
   126  			return nil, E.New("unknown network: ", network)
   127  		}
   128  		var err error
   129  		uid, err = w.iif.FindConnectionOwner(ipProtocol, source.Addr().String(), int32(source.Port()), destination.Addr().String(), int32(destination.Port()))
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  	}
   134  	packageName, _ := w.iif.PackageNameByUid(uid)
   135  	return &process.Info{UserId: uid, PackageName: packageName}, nil
   136  }
   137  
   138  func (w *platformInterfaceWrapper) UsePlatformDefaultInterfaceMonitor() bool {
   139  	return w.iif.UsePlatformDefaultInterfaceMonitor()
   140  }
   141  
   142  func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(errorHandler E.Handler) tun.DefaultInterfaceMonitor {
   143  	return &platformDefaultInterfaceMonitor{
   144  		platformInterfaceWrapper: w,
   145  		errorHandler:             errorHandler,
   146  		defaultInterfaceIndex:    -1,
   147  	}
   148  }
   149  
   150  func (w *platformInterfaceWrapper) UsePlatformInterfaceGetter() bool {
   151  	return w.iif.UsePlatformInterfaceGetter()
   152  }
   153  
   154  func (w *platformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) {
   155  	interfaceIterator, err := w.iif.GetInterfaces()
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	var interfaces []platform.NetworkInterface
   160  	for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
   161  		interfaces = append(interfaces, platform.NetworkInterface{
   162  			Index:     int(netInterface.Index),
   163  			MTU:       int(netInterface.MTU),
   164  			Name:      netInterface.Name,
   165  			Addresses: common.Map(iteratorToArray[string](netInterface.Addresses), netip.MustParsePrefix),
   166  		})
   167  	}
   168  	return interfaces, nil
   169  }