github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/service/ctl.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package service
     5  
     6  import (
     7  	"github.com/keybase/client/go/install"
     8  	"github.com/keybase/client/go/libkb"
     9  	"github.com/keybase/client/go/logger"
    10  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    11  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    12  	"golang.org/x/net/context"
    13  )
    14  
    15  type CtlHandler struct {
    16  	libkb.Contextified
    17  	service *Service
    18  	*BaseHandler
    19  }
    20  
    21  func NewCtlHandler(xp rpc.Transporter, v *Service, g *libkb.GlobalContext) *CtlHandler {
    22  	return &CtlHandler{
    23  		BaseHandler:  NewBaseHandler(g, xp),
    24  		Contextified: libkb.NewContextified(g),
    25  		service:      v,
    26  	}
    27  }
    28  
    29  // Stop is called on the rpc keybase.1.ctl.stop, which shuts down the service.
    30  func (c *CtlHandler) Stop(ctx context.Context, args keybase1.StopArg) error {
    31  	c.G().Log.Debug("Ctl: Stop: StopAllButService")
    32  	install.StopAllButService(libkb.NewMetaContext(ctx, c.G()), args.ExitCode)
    33  	c.G().Log.Debug("Ctl: Stop: Stopping service")
    34  	c.service.Stop(args.ExitCode)
    35  	return nil
    36  }
    37  
    38  func (c *CtlHandler) StopService(ctx context.Context, args keybase1.StopServiceArg) error {
    39  	c.G().Log.Debug("Ctl: StopService")
    40  	c.service.Stop(args.ExitCode)
    41  	return nil
    42  }
    43  
    44  func (c *CtlHandler) LogRotate(_ context.Context, sessionID int) error {
    45  	logFile, _ := c.G().Env.GetEffectiveLogFile()
    46  	// Redirect to log file even if not explicitly desired during service call
    47  	return logger.SetLogFileConfig(c.G().Env.GetLogFileConfig(logFile), nil)
    48  }
    49  
    50  func (c *CtlHandler) Reload(_ context.Context, sessionID int) error {
    51  	c.G().Log.Info("Reloading config file")
    52  	return c.G().ConfigReload()
    53  }
    54  
    55  func (c *CtlHandler) DbClean(ctx context.Context, arg keybase1.DbCleanArg) (err error) {
    56  	mctx := libkb.NewMetaContext(ctx, c.G())
    57  	defer mctx.Trace("DbClean", &err)()
    58  	switch arg.DbType {
    59  	case keybase1.DbType_MAIN:
    60  		return c.G().LocalDb.Clean(arg.Force)
    61  	case keybase1.DbType_CHAT:
    62  		return c.G().LocalChatDb.Clean(arg.Force)
    63  	default:
    64  		return libkb.NewDBError("unsupported DB type")
    65  	}
    66  }
    67  
    68  func (c *CtlHandler) DbNuke(ctx context.Context, sessionID int) (err error) {
    69  	mctx := libkb.NewMetaContext(ctx, c.G())
    70  	defer mctx.Trace("DbNuke", &err)()
    71  	logui := c.getLogUI(sessionID)
    72  
    73  	fn, err := c.G().LocalDb.Nuke()
    74  	if err != nil {
    75  		logui.Warning("Failed to nuke DB: %s", err)
    76  		return err
    77  	}
    78  	logui.Warning("Nuking database %s", fn)
    79  
    80  	fn, err = c.G().LocalChatDb.Nuke()
    81  	if err != nil {
    82  		logui.Warning("Failed to nuke chat DB: %s", err)
    83  		return err
    84  	}
    85  	logui.Warning("Nuking chat database %s", fn)
    86  
    87  	// Now drop caches, since we had the DB's state in-memory too.
    88  	c.G().FlushCaches()
    89  	c.G().CallDbNukeHooks(mctx)
    90  	return nil
    91  }
    92  
    93  func (c *CtlHandler) AppExit(_ context.Context, sessionID int) error {
    94  	c.G().Log.Debug("Received appExit RPC")
    95  	c.G().NotifyRouter.HandleAppExit()
    96  	return nil
    97  }
    98  
    99  func (c *CtlHandler) DbDelete(ctx context.Context, arg keybase1.DbDeleteArg) (err error) {
   100  	mctx := libkb.NewMetaContext(ctx, c.G())
   101  	defer mctx.Trace("DbDelete", &err)()
   102  	key := libkb.ImportDbKey(arg.Key)
   103  
   104  	switch arg.Key.DbType {
   105  	case keybase1.DbType_MAIN:
   106  		err = c.G().LocalDb.Delete(key)
   107  	case keybase1.DbType_CHAT:
   108  		err = c.G().LocalChatDb.Delete(key)
   109  	default:
   110  		err = libkb.NewDBError("no such DB type")
   111  	}
   112  
   113  	if err != nil {
   114  		return err
   115  	}
   116  
   117  	c.G().Log.Debug("Clearing memory caches after DbDelete")
   118  	c.G().FlushCaches()
   119  
   120  	return nil
   121  }
   122  
   123  func (c *CtlHandler) DbGet(ctx context.Context, arg keybase1.DbGetArg) (ret *keybase1.DbValue, err error) {
   124  	mctx := libkb.NewMetaContext(ctx, c.G())
   125  	defer mctx.Trace("DbGet", &err)()
   126  	key := libkb.ImportDbKey(arg.Key)
   127  	var res []byte
   128  	var found bool
   129  	switch arg.Key.DbType {
   130  	case keybase1.DbType_MAIN:
   131  		res, found, err = c.G().LocalDb.GetRaw(key)
   132  	case keybase1.DbType_CHAT:
   133  		res, found, err = c.G().LocalChatDb.GetRaw(key)
   134  	default:
   135  		return nil, libkb.NewDBError("no such DB type")
   136  	}
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	if !found {
   141  		return nil, nil
   142  	}
   143  	val := keybase1.DbValue(res)
   144  	return &val, nil
   145  }
   146  
   147  func (c *CtlHandler) DbKeysWithPrefixes(ctx context.Context, arg keybase1.DbKeysWithPrefixesArg) (ret []keybase1.DbKey, err error) {
   148  	mctx := libkb.NewMetaContext(ctx, c.G())
   149  	defer mctx.Trace("DbKeysWithPrefixes", &err)()
   150  	var res libkb.DBKeySet
   151  	switch arg.Prefix.DbType {
   152  	case keybase1.DbType_MAIN:
   153  		res, err = c.G().LocalDb.KeysWithPrefixes([]byte(libkb.PrefixString(libkb.ObjType(arg.Prefix.ObjType))))
   154  	case keybase1.DbType_CHAT:
   155  		res, err = c.G().LocalChatDb.KeysWithPrefixes([]byte(libkb.PrefixString(libkb.ObjType(arg.Prefix.ObjType))))
   156  	default:
   157  		return nil, libkb.NewDBError("no such DB type")
   158  	}
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	ret = make([]keybase1.DbKey, 0, len(res))
   164  	for k := range res {
   165  		ret = append(ret, keybase1.DbKey{
   166  			DbType:  arg.Prefix.DbType,
   167  			ObjType: int(k.Typ),
   168  			Key:     k.Key,
   169  		})
   170  	}
   171  
   172  	return ret, nil
   173  }
   174  
   175  func (c *CtlHandler) DbPut(ctx context.Context, arg keybase1.DbPutArg) (err error) {
   176  	mctx := libkb.NewMetaContext(ctx, c.G())
   177  	defer mctx.Trace("DbPut", &err)()
   178  	key := libkb.ImportDbKey(arg.Key)
   179  
   180  	switch arg.Key.DbType {
   181  	case keybase1.DbType_MAIN:
   182  		err = c.G().LocalDb.PutRaw(key, []byte(arg.Value))
   183  	case keybase1.DbType_CHAT:
   184  		err = c.G().LocalChatDb.PutRaw(key, []byte(arg.Value))
   185  	default:
   186  		err = libkb.NewDBError("no such DB type")
   187  	}
   188  
   189  	if err != nil {
   190  		return err
   191  	}
   192  
   193  	c.G().Log.Debug("Clearing memory caches after DbPut")
   194  	c.G().FlushCaches()
   195  
   196  	return nil
   197  }