sing-box/experimental/libbox/service.go

293 lines
8.8 KiB
Go
Raw Normal View History

2022-10-25 12:55:00 +08:00
package libbox
import (
"context"
"net/netip"
"os"
2023-11-15 13:05:33 +08:00
"runtime"
2023-08-12 19:33:43 +08:00
runtimeDebug "runtime/debug"
2024-11-11 16:23:45 +08:00
"sync"
2022-10-25 12:55:00 +08:00
"syscall"
"time"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing-box"
2023-04-18 14:04:09 +08:00
"github.com/sagernet/sing-box/adapter"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing-box/common/process"
2023-07-02 16:45:30 +08:00
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
2024-10-18 09:58:03 +08:00
"github.com/sagernet/sing-box/experimental/deprecated"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
"github.com/sagernet/sing-box/experimental/libbox/platform"
2024-11-02 00:39:02 +08:00
"github.com/sagernet/sing-box/include"
2023-11-15 13:05:33 +08:00
"github.com/sagernet/sing-box/log"
2023-02-28 19:02:27 +08:00
"github.com/sagernet/sing-box/option"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing-tun"
2023-04-18 14:04:09 +08:00
"github.com/sagernet/sing/common"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
2023-07-23 14:42:19 +08:00
"github.com/sagernet/sing/common/logger"
2022-10-25 12:55:00 +08:00
N "github.com/sagernet/sing/common/network"
2023-07-02 16:45:30 +08:00
"github.com/sagernet/sing/service"
2023-04-21 17:29:00 +08:00
"github.com/sagernet/sing/service/filemanager"
2023-08-07 17:46:51 +08:00
"github.com/sagernet/sing/service/pause"
2022-10-25 12:55:00 +08:00
)
type BoxService struct {
ctx context.Context
cancel context.CancelFunc
2024-11-10 16:46:59 +08:00
urlTestHistoryStorage *urltest.HistoryStorage
instance *box.Box
2024-11-10 16:46:59 +08:00
clashServer adapter.ClashServer
pauseManager pause.Manager
servicePauseFields
2022-10-25 12:55:00 +08:00
}
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
2024-11-21 18:10:41 +08:00
ctx := box.Context(context.Background(), include.InboundRegistry(), include.OutboundRegistry(), include.EndpointRegistry())
2024-11-07 12:02:36 +08:00
ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID)
2024-11-10 16:46:59 +08:00
service.MustRegister[deprecated.Manager](ctx, new(deprecatedManager))
2024-11-02 00:39:02 +08:00
options, err := parseConfig(ctx, configContent)
2022-10-25 12:55:00 +08:00
if err != nil {
return nil, err
}
2023-08-12 19:33:43 +08:00
runtimeDebug.FreeOSMemory()
2024-11-02 00:39:02 +08:00
ctx, cancel := context.WithCancel(ctx)
urlTestHistoryStorage := urltest.NewHistoryStorage()
ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage)
2024-11-11 16:23:45 +08:00
platformWrapper := &platformInterfaceWrapper{
iif: platformInterface,
useProcFS: platformInterface.UseProcFS(),
}
2024-11-10 16:46:59 +08:00
service.MustRegister[platform.Interface](ctx, platformWrapper)
2023-04-03 18:24:20 +08:00
instance, err := box.New(box.Options{
Context: ctx,
Options: options,
2023-11-15 13:05:33 +08:00
PlatformLogWriter: platformWrapper,
2023-04-03 18:24:20 +08:00
})
2022-10-25 12:55:00 +08:00
if err != nil {
cancel()
return nil, E.Cause(err, "create service")
}
2023-08-12 19:33:43 +08:00
runtimeDebug.FreeOSMemory()
2022-10-25 12:55:00 +08:00
return &BoxService{
ctx: ctx,
cancel: cancel,
instance: instance,
urlTestHistoryStorage: urlTestHistoryStorage,
2023-12-16 15:40:14 +08:00
pauseManager: service.FromContext[pause.Manager](ctx),
2024-11-10 16:46:59 +08:00
clashServer: service.FromContext[adapter.ClashServer](ctx),
2022-10-25 12:55:00 +08:00
}, nil
}
func (s *BoxService) Start() error {
2024-12-10 09:58:55 +08:00
if C.FixAndroidStack {
var err error
done := make(chan struct{})
go func() {
err = s.instance.Start()
close(done)
}()
<-done
return err
} else {
return s.instance.Start()
}
2022-10-25 12:55:00 +08:00
}
func (s *BoxService) Close() error {
2024-12-10 09:58:55 +08:00
s.cancel()
s.urlTestHistoryStorage.Close()
var err error
done := make(chan struct{})
go func() {
2024-12-10 09:58:55 +08:00
err = s.instance.Close()
close(done)
}()
2024-12-10 09:58:55 +08:00
select {
case <-done:
return err
case <-time.After(C.FatalStopTimeout):
os.Exit(1)
return nil
}
2022-10-25 12:55:00 +08:00
}
func (s *BoxService) NeedWIFIState() bool {
return s.instance.Router().NeedWIFIState()
}
2023-11-15 13:05:33 +08:00
var (
_ platform.Interface = (*platformInterfaceWrapper)(nil)
_ log.PlatformWriter = (*platformInterfaceWrapper)(nil)
)
2022-10-25 12:55:00 +08:00
type platformInterfaceWrapper struct {
2024-11-11 16:23:45 +08:00
iif PlatformInterface
useProcFS bool
networkManager adapter.NetworkManager
myTunName string
defaultInterfaceAccess sync.Mutex
defaultInterface *control.Interface
isExpensive bool
isConstrained bool
2023-04-18 14:04:09 +08:00
}
2024-11-10 12:11:21 +08:00
func (w *platformInterfaceWrapper) Initialize(networkManager adapter.NetworkManager) error {
w.networkManager = networkManager
2023-04-18 14:04:09 +08:00
return nil
2022-10-25 12:55:00 +08:00
}
func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
return w.iif.UsePlatformAutoDetectInterfaceControl()
}
2024-11-06 12:51:53 +08:00
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl(fd int) error {
return w.iif.AutoDetectInterfaceControl(int32(fd))
2022-10-25 12:55:00 +08:00
}
func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
2022-10-25 12:55:00 +08:00
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
2024-12-23 22:24:10 +08:00
return nil, E.New("platform: unsupported uid options")
2022-10-25 12:55:00 +08:00
}
if len(options.IncludeAndroidUser) > 0 {
2024-12-23 22:24:10 +08:00
return nil, E.New("platform: unsupported android_user option")
2022-10-25 12:55:00 +08:00
}
routeRanges, err := options.BuildAutoRouteRanges(true)
if err != nil {
return nil, err
}
tunFd, err := w.iif.OpenTun(&tunOptions{options, routeRanges, platformOptions})
2022-10-25 12:55:00 +08:00
if err != nil {
return nil, err
}
options.Name, err = getTunnelName(tunFd)
if err != nil {
return nil, E.Cause(err, "query tun name")
}
2023-04-07 21:10:16 +08:00
dupFd, err := dup(int(tunFd))
2023-03-13 19:47:00 +08:00
if err != nil {
return nil, E.Cause(err, "dup tun file descriptor")
}
options.FileDescriptor = dupFd
2024-11-11 16:23:45 +08:00
w.myTunName = options.Name
return tun.New(*options)
2022-10-25 12:55:00 +08:00
}
2024-12-23 22:24:10 +08:00
func (w *platformInterfaceWrapper) UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error {
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
return E.New("android: unsupported uid options")
}
if len(options.IncludeAndroidUser) > 0 {
return E.New("android: unsupported android_user option")
}
routeRanges, err := options.BuildAutoRouteRanges(true)
if err != nil {
return err
}
return w.iif.UpdateRouteOptions(&tunOptions{options, routeRanges, platformOptions})
}
2023-07-23 14:42:19 +08:00
func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
2023-04-18 14:04:09 +08:00
return &platformDefaultInterfaceMonitor{
platformInterfaceWrapper: w,
2023-07-23 14:42:19 +08:00
logger: logger,
2023-04-18 14:04:09 +08:00
}
}
2024-11-11 16:23:45 +08:00
func (w *platformInterfaceWrapper) Interfaces() ([]adapter.NetworkInterface, error) {
2023-04-18 14:04:09 +08:00
interfaceIterator, err := w.iif.GetInterfaces()
if err != nil {
return nil, err
}
2024-11-11 16:23:45 +08:00
var interfaces []adapter.NetworkInterface
2023-04-18 14:04:09 +08:00
for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
2024-11-11 16:23:45 +08:00
if netInterface.Name == w.myTunName {
continue
}
w.defaultInterfaceAccess.Lock()
isDefault := w.defaultInterface != nil && int(netInterface.Index) == w.defaultInterface.Index
w.defaultInterfaceAccess.Unlock()
interfaces = append(interfaces, adapter.NetworkInterface{
Interface: control.Interface{
Index: int(netInterface.Index),
MTU: int(netInterface.MTU),
Name: netInterface.Name,
Addresses: common.Map(iteratorToArray[string](netInterface.Addresses), netip.MustParsePrefix),
Flags: linkFlags(uint32(netInterface.Flags)),
},
2024-11-13 19:05:28 +08:00
Type: C.InterfaceType(netInterface.Type),
2024-11-11 16:23:45 +08:00
DNSServers: iteratorToArray[string](netInterface.DNSServer),
Expensive: netInterface.Metered || isDefault && w.isExpensive,
Constrained: isDefault && w.isConstrained,
RawNetwork: netInterface.RawNetwork,
2023-04-18 14:04:09 +08:00
})
}
return interfaces, nil
}
func (w *platformInterfaceWrapper) SetUnderlyingNetworks(networks []adapter.NetworkInterface) error {
return w.iif.SetUnderlyingNetworks(newIterator(common.Map(networks, func(it adapter.NetworkInterface) RawNetwork {
return it.RawNetwork.(RawNetwork)
})))
}
func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
return w.iif.UnderNetworkExtension()
}
2024-05-07 20:34:24 +08:00
func (w *platformInterfaceWrapper) IncludeAllNetworks() bool {
return w.iif.IncludeAllNetworks()
}
func (w *platformInterfaceWrapper) ClearDNSCache() {
w.iif.ClearDNSCache()
}
2023-11-15 13:05:33 +08:00
func (w *platformInterfaceWrapper) ReadWIFIState() adapter.WIFIState {
wifiState := w.iif.ReadWIFIState()
if wifiState == nil {
return adapter.WIFIState{}
}
return (adapter.WIFIState)(*wifiState)
}
2024-06-11 21:16:33 +08:00
func (w *platformInterfaceWrapper) FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*process.Info, error) {
var uid int32
if w.useProcFS {
uid = procfs.ResolveSocketByProcSearch(network, source, destination)
if uid == -1 {
return nil, E.New("procfs: not found")
}
} else {
var ipProtocol int32
switch N.NetworkName(network) {
case N.NetworkTCP:
ipProtocol = syscall.IPPROTO_TCP
case N.NetworkUDP:
ipProtocol = syscall.IPPROTO_UDP
default:
return nil, E.New("unknown network: ", network)
}
var err error
uid, err = w.iif.FindConnectionOwner(ipProtocol, source.Addr().String(), int32(source.Port()), destination.Addr().String(), int32(destination.Port()))
if err != nil {
return nil, err
}
}
packageName, _ := w.iif.PackageNameByUid(uid)
return &process.Info{UserId: uid, PackageName: packageName}, nil
}
2023-11-15 13:05:33 +08:00
func (w *platformInterfaceWrapper) DisableColors() bool {
return runtime.GOOS != "android"
}
func (w *platformInterfaceWrapper) WriteMessage(level log.Level, message string) {
w.iif.WriteLog(message)
}
2024-11-06 12:51:53 +08:00
func (w *platformInterfaceWrapper) SendNotification(notification *platform.Notification) error {
return w.iif.SendNotification((*Notification)(notification))
}