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 }