github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/upakfinder.go (about) 1 package chat 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 8 "github.com/keybase/client/go/chat/globals" 9 "github.com/keybase/client/go/chat/utils" 10 "github.com/keybase/client/go/libkb" 11 "github.com/keybase/client/go/protocol/keybase1" 12 ) 13 14 type udStoredRes struct { 15 username libkb.NormalizedUsername 16 deviceName string 17 deviceType keybase1.DeviceTypeV2 18 } 19 20 type checkKidStoredRes struct { 21 found bool 22 revokedAt *keybase1.KeybaseTime 23 deleted bool 24 } 25 26 type CachingUPAKFinder struct { 27 globals.Contextified 28 utils.DebugLabeler 29 30 udLock sync.RWMutex 31 udCache map[string]udStoredRes 32 checkKidLock sync.RWMutex 33 checkKidCache map[string]checkKidStoredRes 34 } 35 36 func NewCachingUPAKFinder(g *globals.Context) *CachingUPAKFinder { 37 return &CachingUPAKFinder{ 38 Contextified: globals.NewContextified(g), 39 DebugLabeler: utils.NewDebugLabeler(g.ExternalG(), "CachingUPAKFinder", false), 40 udCache: make(map[string]udStoredRes), 41 checkKidCache: make(map[string]checkKidStoredRes), 42 } 43 } 44 45 func (u *CachingUPAKFinder) udKey(uid keybase1.UID, deviceID keybase1.DeviceID) string { 46 return fmt.Sprintf("ud:%s:%s", uid, deviceID) 47 } 48 49 func (u *CachingUPAKFinder) checkKidKey(uid keybase1.UID, kid keybase1.KID) string { 50 return fmt.Sprintf("ck:%s:%s", uid, kid) 51 } 52 53 func (u *CachingUPAKFinder) lookupUDKey(key string) (udStoredRes, bool) { 54 u.udLock.RLock() 55 defer u.udLock.RUnlock() 56 existing, ok := u.udCache[key] 57 return existing, ok 58 } 59 60 func (u *CachingUPAKFinder) writeUDKey(key string, username libkb.NormalizedUsername, deviceName string, deviceType keybase1.DeviceTypeV2) { 61 u.udLock.Lock() 62 defer u.udLock.Unlock() 63 u.udCache[key] = udStoredRes{ 64 username: username, 65 deviceName: deviceName, 66 deviceType: deviceType, 67 } 68 } 69 70 func (u *CachingUPAKFinder) lookupCheckKidKey(key string) (checkKidStoredRes, bool) { 71 u.checkKidLock.RLock() 72 defer u.checkKidLock.RUnlock() 73 existing, ok := u.checkKidCache[key] 74 return existing, ok 75 } 76 77 func (u *CachingUPAKFinder) writeCheckKidKey(key string, found bool, revokedAt *keybase1.KeybaseTime, 78 deleted bool) { 79 u.checkKidLock.Lock() 80 defer u.checkKidLock.Unlock() 81 u.checkKidCache[key] = checkKidStoredRes{ 82 found: found, 83 revokedAt: revokedAt, 84 deleted: deleted, 85 } 86 } 87 88 func (u *CachingUPAKFinder) LookupUsernameAndDevice(ctx context.Context, uid keybase1.UID, deviceID keybase1.DeviceID) (username libkb.NormalizedUsername, deviceName string, deviceType keybase1.DeviceTypeV2, err error) { 89 key := u.udKey(uid, deviceID) 90 existing, ok := u.lookupUDKey(key) 91 if ok { 92 return existing.username, existing.deviceName, existing.deviceType, nil 93 } 94 defer func() { 95 if err == nil { 96 u.writeUDKey(key, username, deviceName, deviceType) 97 } 98 }() 99 return u.G().GetUPAKLoader().LookupUsernameAndDevice(ctx, uid, deviceID) 100 } 101 102 func (u *CachingUPAKFinder) CheckKIDForUID(ctx context.Context, uid keybase1.UID, kid keybase1.KID) (found bool, revokedAt *keybase1.KeybaseTime, deleted bool, err error) { 103 key := u.checkKidKey(uid, kid) 104 existing, ok := u.lookupCheckKidKey(key) 105 if ok { 106 return existing.found, existing.revokedAt, existing.deleted, nil 107 } 108 defer func() { 109 if err == nil { 110 u.writeCheckKidKey(key, found, revokedAt, deleted) 111 } 112 }() 113 return u.G().GetUPAKLoader().CheckKIDForUID(ctx, uid, kid) 114 }