move gotd fork into repo. (#111)
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
// Package salts contains MTProto server salt storage.
|
||||
package salts
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/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()
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package salts
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/mt"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/testutil"
|
||||
)
|
||||
|
||||
func generateSalts(n int) []mt.FutureSalt {
|
||||
r := make([]mt.FutureSalt, n)
|
||||
for i := range r {
|
||||
since := (i + 1) * 10
|
||||
|
||||
r[i] = mt.FutureSalt{
|
||||
ValidSince: since,
|
||||
ValidUntil: since + 15,
|
||||
Salt: int64(i),
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func TestSalts(t *testing.T) {
|
||||
a := require.New(t)
|
||||
salts := &Salts{}
|
||||
var testData = []mt.FutureSalt{
|
||||
{
|
||||
ValidSince: 10,
|
||||
ValidUntil: 25,
|
||||
Salt: 1,
|
||||
},
|
||||
{
|
||||
ValidSince: 20,
|
||||
ValidUntil: 35,
|
||||
Salt: 2,
|
||||
},
|
||||
{
|
||||
ValidSince: 30,
|
||||
ValidUntil: 45,
|
||||
Salt: 3,
|
||||
},
|
||||
}
|
||||
|
||||
salts.Store(testData[:2])
|
||||
a.Len(salts.salts, 2)
|
||||
|
||||
salt, ok := salts.Get(time.Unix(11, 0))
|
||||
a.Equal(int64(1), salt)
|
||||
a.True(ok)
|
||||
|
||||
_, ok = salts.Get(time.Unix(36, 0))
|
||||
a.False(ok)
|
||||
|
||||
salts.Store(testData[:2])
|
||||
a.Len(salts.salts, 2)
|
||||
|
||||
salts.Store(testData[:3])
|
||||
a.Len(salts.salts, 3)
|
||||
|
||||
salt, ok = salts.Get(time.Unix(26, 0))
|
||||
a.Equal(int64(2), salt)
|
||||
a.True(ok)
|
||||
|
||||
salt, ok = salts.Get(time.Unix(36, 0))
|
||||
a.Equal(int64(3), salt)
|
||||
a.True(ok)
|
||||
|
||||
salts.Reset()
|
||||
_, ok = salts.Get(time.Unix(36, 0))
|
||||
a.False(ok)
|
||||
}
|
||||
|
||||
func TestSalts_Get(t *testing.T) {
|
||||
salts := &Salts{}
|
||||
salts.Store(generateSalts(64))
|
||||
|
||||
now := time.Unix(11, 0)
|
||||
testutil.ZeroAlloc(t, func() {
|
||||
salts.Get(now)
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkSalts_Get(b *testing.B) {
|
||||
salts := &Salts{}
|
||||
salts.Store(generateSalts(64))
|
||||
t := time.Unix(11, 0)
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
salts.Get(t)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSalts_Store(b *testing.B) {
|
||||
testData := generateSalts(64)
|
||||
salts := &Salts{
|
||||
salts: make([]mt.FutureSalt, 0, len(testData)),
|
||||
}
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
salts.Store(testData)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user