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  }