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