sing-box/experimental/libbox/service.go

259 lines
7.8 KiB
Go
Raw Permalink Normal View History

2022-10-25 04:55:00 +00:00
package libbox
import (
"context"
"net/netip"
"os"
2023-11-15 05:05:33 +00:00
"runtime"
2023-08-12 11:33:43 +00:00
runtimeDebug "runtime/debug"
2024-11-11 08:23:45 +00:00
"sync"
2022-10-25 04:55:00 +00:00
"syscall"
"time"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing-box"
2023-04-18 06:04:09 +00:00
"github.com/sagernet/sing-box/adapter"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing-box/common/process"
2023-07-02 08:45:30 +00:00
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
2024-10-18 01:58:03 +00:00
"github.com/sagernet/sing-box/experimental/deprecated"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
"github.com/sagernet/sing-box/experimental/libbox/platform"
2024-11-01 16:39:02 +00:00
"github.com/sagernet/sing-box/include"
2023-11-15 05:05:33 +00:00
"github.com/sagernet/sing-box/log"
2023-02-28 11:02:27 +00:00
"github.com/sagernet/sing-box/option"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing-tun"
2023-04-18 06:04:09 +00:00
"github.com/sagernet/sing/common"
2022-10-25 04:55:00 +00:00
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
2023-07-23 06:42:19 +00:00
"github.com/sagernet/sing/common/logger"
2022-10-25 04:55:00 +00:00
N "github.com/sagernet/sing/common/network"
2023-07-02 08:45:30 +00:00
"github.com/sagernet/sing/service"
2023-04-21 09:29:00 +00:00
"github.com/sagernet/sing/service/filemanager"
2023-08-07 09:46:51 +00:00
"github.com/sagernet/sing/service/pause"
2022-10-25 04:55:00 +00:00
)
type BoxService struct {
ctx context.Context
cancel context.CancelFunc
urlTestHistoryStorage *urltest.HistoryStorage
instance *box.Box
clashServer adapter.ClashServer
pauseManager pause.Manager
servicePauseFields
2022-10-25 04:55:00 +00:00
}
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
2024-11-01 16:39:02 +00:00
ctx := box.Context(context.Background(), include.InboundRegistry(), include.OutboundRegistry())
2024-11-07 04:02:36 +00:00
ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID)
service.MustRegister[deprecated.Manager](ctx, new(deprecatedManager))
2024-11-01 16:39:02 +00:00
options, err := parseConfig(ctx, configContent)
2022-10-25 04:55:00 +00:00
if err != nil {
return nil, err
}
2023-08-12 11:33:43 +00:00
runtimeDebug.FreeOSMemory()
2024-11-01 16:39:02 +00:00
ctx, cancel := context.WithCancel(ctx)
urlTestHistoryStorage := urltest.NewHistoryStorage()
ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage)
2024-11-11 08:23:45 +00:00
platformWrapper := &platformInterfaceWrapper{
iif: platformInterface,
useProcFS: platformInterface.UseProcFS(),
}
service.MustRegister[platform.Interface](ctx, platformWrapper)
2023-04-03 10:24:20 +00:00
instance, err := box.New(box.Options{
Context: ctx,
Options: options,
2023-11-15 05:05:33 +00:00
PlatformLogWriter: platformWrapper,
2023-04-03 10:24:20 +00:00
})
2022-10-25 04:55:00 +00:00
if err != nil {
cancel()
return nil, E.Cause(err, "create service")
}
2023-08-12 11:33:43 +00:00
runtimeDebug.FreeOSMemory()
2022-10-25 04:55:00 +00:00
return &BoxService{
ctx: ctx,
cancel: cancel,
instance: instance,
urlTestHistoryStorage: urlTestHistoryStorage,
2023-12-16 07:40:14 +00:00
pauseManager: service.FromContext[pause.Manager](ctx),
clashServer: service.FromContext[adapter.ClashServer](ctx),
2022-10-25 04:55:00 +00:00
}, nil
}
func (s *BoxService) Start() error {
return s.instance.Start()
}
func (s *BoxService) Close() error {
done := make(chan struct{})
defer close(done)
go func() {
select {
case <-done:
return
2024-04-02 15:07:26 +00:00
case <-time.After(C.FatalStopTimeout):
os.Exit(1)
}
}()
2022-10-25 04:55:00 +00:00
s.cancel()
s.urlTestHistoryStorage.Close()
2022-10-25 04:55:00 +00:00
return s.instance.Close()
}
func (s *BoxService) NeedWIFIState() bool {
return s.instance.Router().NeedWIFIState()
}
2023-11-15 05:05:33 +00:00
var (
_ platform.Interface = (*platformInterfaceWrapper)(nil)
_ log.PlatformWriter = (*platformInterfaceWrapper)(nil)
)
2022-10-25 04:55:00 +00:00
type platformInterfaceWrapper struct {
2024-11-11 08:23:45 +00:00
iif PlatformInterface
useProcFS bool
networkManager adapter.NetworkManager
myTunName string
defaultInterfaceAccess sync.Mutex
defaultInterface *control.Interface
isExpensive bool
isConstrained bool
2023-04-18 06:04:09 +00:00
}
2024-11-10 04:11:21 +00:00
func (w *platformInterfaceWrapper) Initialize(networkManager adapter.NetworkManager) error {
w.networkManager = networkManager
2023-04-18 06:04:09 +00:00
return nil
2022-10-25 04:55:00 +00:00
}
func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
return w.iif.UsePlatformAutoDetectInterfaceControl()
}
2024-11-06 04:51:53 +00:00
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl(fd int) error {
return w.iif.AutoDetectInterfaceControl(int32(fd))
2022-10-25 04:55:00 +00:00
}
func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
2022-10-25 04:55:00 +00:00
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
return nil, E.New("android: unsupported uid options")
}
if len(options.IncludeAndroidUser) > 0 {
return nil, E.New("android: unsupported android_user option")
}
routeRanges, err := options.BuildAutoRouteRanges(true)
if err != nil {
return nil, err
}
tunFd, err := w.iif.OpenTun(&tunOptions{options, routeRanges, platformOptions})
2022-10-25 04:55:00 +00: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 13:10:16 +00:00
dupFd, err := dup(int(tunFd))
2023-03-13 11:47:00 +00:00
if err != nil {
return nil, E.Cause(err, "dup tun file descriptor")
}
options.FileDescriptor = dupFd
2024-11-11 08:23:45 +00:00
w.myTunName = options.Name
return tun.New(*options)
2022-10-25 04:55:00 +00:00
}
2023-07-23 06:42:19 +00:00
func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
2023-04-18 06:04:09 +00:00
return &platformDefaultInterfaceMonitor{
platformInterfaceWrapper: w,
2023-07-23 06:42:19 +00:00
logger: logger,
2023-04-18 06:04:09 +00:00
}
}
2024-11-11 08:23:45 +00:00
func (w *platformInterfaceWrapper) Interfaces() ([]adapter.NetworkInterface, error) {
2023-04-18 06:04:09 +00:00
interfaceIterator, err := w.iif.GetInterfaces()
if err != nil {
return nil, err
}
2024-11-11 08:23:45 +00:00
var interfaces []adapter.NetworkInterface
2023-04-18 06:04:09 +00:00
for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
2024-11-11 08:23:45 +00: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 11:05:28 +00:00
Type: C.InterfaceType(netInterface.Type),
2024-11-11 08:23:45 +00:00
DNSServers: iteratorToArray[string](netInterface.DNSServer),
Expensive: netInterface.Metered || isDefault && w.isExpensive,
Constrained: isDefault && w.isConstrained,
2023-04-18 06:04:09 +00:00
})
}
return interfaces, nil
}
func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
return w.iif.UnderNetworkExtension()
}
2024-05-07 12:34:24 +00:00
func (w *platformInterfaceWrapper) IncludeAllNetworks() bool {
return w.iif.IncludeAllNetworks()
}
func (w *platformInterfaceWrapper) ClearDNSCache() {
w.iif.ClearDNSCache()
}
2023-11-15 05:05:33 +00:00
func (w *platformInterfaceWrapper) ReadWIFIState() adapter.WIFIState {
wifiState := w.iif.ReadWIFIState()
if wifiState == nil {
return adapter.WIFIState{}
}
return (adapter.WIFIState)(*wifiState)
}
2024-06-11 13:16:33 +00: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 05:05:33 +00: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 04:51:53 +00:00
func (w *platformInterfaceWrapper) SendNotification(notification *platform.Notification) error {
return w.iif.SendNotification((*Notification)(notification))
}