package daemon import ( "context" "time" "unsafe" "github.com/sagernet/sing-box/service/oomkiller" "github.com/sagernet/sing/common/memory" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" ) var _ ManagedServiceServer = (*ManagedService)(nil) type ManagedService struct { handler ManagedHandler debug bool oomReporter oomkiller.OOMReporter } type ManagedServiceOptions struct { Handler ManagedHandler Debug bool OOMReporter oomkiller.OOMReporter } func NewManagedService(options ManagedServiceOptions) *ManagedService { return &ManagedService{ handler: options.Handler, debug: options.Debug, oomReporter: options.OOMReporter, } } func (s *ManagedService) StopService(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { err := s.handler.ServiceStop() if err != nil { return nil, err } return &emptypb.Empty{}, nil } func (s *ManagedService) ReloadService(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { err := s.handler.ServiceReload(ctx) if err != nil { return nil, err } return &emptypb.Empty{}, nil } func (s *ManagedService) GetSystemProxyStatus(ctx context.Context, empty *emptypb.Empty) (*SystemProxyStatus, error) { return s.handler.SystemProxyStatus() } func (s *ManagedService) SetSystemProxyEnabled(ctx context.Context, request *SetSystemProxyEnabledRequest) (*emptypb.Empty, error) { err := s.handler.SetSystemProxyEnabled(request.Enabled) if err != nil { return nil, err } return &emptypb.Empty{}, nil } func (s *ManagedService) TriggerDebugCrash(ctx context.Context, request *DebugCrashRequest) (*emptypb.Empty, error) { if !s.debug { return nil, status.Error(codes.PermissionDenied, "debug crash trigger unavailable") } if request == nil { return nil, status.Error(codes.InvalidArgument, "missing debug crash request") } switch request.Type { case DebugCrashRequest_GO: time.AfterFunc(200*time.Millisecond, func() { *(*int)(unsafe.Pointer(uintptr(0))) = 0 }) case DebugCrashRequest_NATIVE: err := s.handler.TriggerNativeCrash() if err != nil { return nil, err } default: return nil, status.Error(codes.InvalidArgument, "unknown debug crash type") } return &emptypb.Empty{}, nil } func (s *ManagedService) TriggerOOMReport(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) { if s.oomReporter == nil { return nil, status.Error(codes.Unavailable, "OOM reporter not available") } return &emptypb.Empty{}, s.oomReporter.WriteReport(memory.Total()) } func (s *ManagedService) mustEmbedUnimplementedManagedServiceServer() { }