You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
1.7 KiB
91 lines
1.7 KiB
3 years ago
|
// 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()
|
||
|
}
|