-
-
Notifications
You must be signed in to change notification settings - Fork 119
/
salts.go
90 lines (75 loc) · 1.68 KB
/
salts.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
// Package salts contains MTProto server salt storage.
package salts
import (
"sort"
"sync"
"time"
"github.com/gotd/td/internal/mt"
)
// Salts is a simple struct store server salts.
type Salts struct {
// server salts fetched by getSalts.
salts []mt.FutureSalt
saltsMux sync.Mutex
}
// Get returns next valid salt.
func (s *Salts) Get(deadline time.Time) (int64, bool) {
s.saltsMux.Lock()
defer s.saltsMux.Unlock()
check:
if len(s.salts) < 1 {
return 0, false
}
date := int(deadline.Unix())
if salt := s.salts[len(s.salts)-1]; salt.ValidUntil > date {
return salt.Salt, true
}
// Filter (in place) from SliceTricks.
n := 0
// Check that the salt will be valid until deadline.
for _, salt := range s.salts {
// Filter expired salts.
if salt.ValidUntil > date {
// Keep valid salt.
s.salts[n] = salt
n++
}
}
s.salts = s.salts[:n]
goto check
}
type saltSlice []mt.FutureSalt
func (s saltSlice) Len() int {
return len(s)
}
func (s saltSlice) Less(i, j int) bool {
return s[i].ValidUntil > s[j].ValidUntil
}
func (s saltSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Store stores all given salts.
func (s *Salts) Store(salts []mt.FutureSalt) {
s.saltsMux.Lock()
defer s.saltsMux.Unlock()
s.salts = append(s.salts, salts...)
// Filter duplicates.
n := 0
dedup := make(map[int64]struct{}, len(s.salts)+1)
for _, salt := range s.salts {
if _, ok := dedup[salt.Salt]; !ok {
dedup[salt.Salt] = struct{}{}
s.salts[n] = salt
n++
}
}
s.salts = s.salts[:n]
// Sort slice by valid until.
sort.Sort(saltSlice(s.salts))
}
// Reset deletes all stored salts.
func (s *Salts) Reset() {
s.saltsMux.Lock()
s.salts = s.salts[:0]
s.saltsMux.Unlock()
}