package telegram
import (
"context"
"fmt"
"github.com/go-faster/errors"
"github.com/gotd/log"
"github.com/gotd/td/crypto"
"github.com/gotd/td/mtproto"
"github.com/gotd/td/pool"
"github.com/gotd/td/session"
"github.com/gotd/td/tg"
)
func (c *Client ) restoreConnection (ctx context .Context ) error {
if c .storage == nil {
return nil
}
data , err := c .storage .Load (ctx )
if errors .Is (err , session .ErrNotFound ) {
return nil
}
if err != nil {
return errors .Wrap (err , "load" )
}
prev := c .session .Load ()
if data .DC == 0 {
data .DC = prev .DC
}
var key crypto .AuthKey
copy (key .Value [:], data .AuthKey )
copy (key .ID [:], data .AuthKeyID )
if key .Value .ID () != key .ID {
return errors .New ("corrupted key" )
}
c .log .Info (ctx , "Connection restored from state" ,
log .String ("addr" , data .Addr ),
log .String ("key_id" , fmt .Sprintf ("%x" , data .AuthKeyID )),
)
c .connMux .Lock ()
c .session .Store (pool .Session {
DC : data .DC ,
AuthKey : key ,
Salt : data .Salt ,
})
c .replaceConn (c .createPrimaryConn (nil ))
c .connMux .Unlock ()
return nil
}
func (c *Client ) saveSession (cfg tg .Config , s mtproto .Session ) error {
if c .storage == nil {
return nil
}
data , err := c .storage .Load (c .ctx )
if errors .Is (err , session .ErrNotFound ) {
err = nil
data = &session .Data {}
}
if err != nil {
return errors .Wrap (err , "load" )
}
data .Config = session .ConfigFromTG (cfg )
keyToSave := s .Key
if !s .PermKey .Zero () {
keyToSave = s .PermKey
}
data .AuthKey = keyToSave .Value [:]
data .AuthKeyID = keyToSave .ID [:]
data .DC = cfg .ThisDC
data .Salt = s .Salt
if err := c .storage .Save (c .ctx , data ); err != nil {
return errors .Wrap (err , "save" )
}
c .log .Debug (c .ctx , "Data saved" ,
log .String ("key_id" , fmt .Sprintf ("%x" , data .AuthKeyID )),
)
return nil
}
func (c *Client ) onSession (cfg tg .Config , s mtproto .Session ) error {
sessionData := dcSessionFromMTProto (cfg .ThisDC , s )
c .storeDCSess (c .sessions , sessionData )
primaryDC := c .session .Load ().DC
if cfg .ThisDC != 0 && primaryDC != 0 && primaryDC != cfg .ThisDC {
return nil
}
c .connMux .Lock ()
c .session .Store (sessionData )
c .cfg .Store (cfg )
c .onReady ()
c .connMux .Unlock ()
if err := c .saveSession (cfg , s ); err != nil {
return errors .Wrap (err , "save" )
}
return nil
}
func (c *Client ) onCDNSession (cfg tg .Config , s mtproto .Session ) error {
c .storeDCSess (c .cdnSessions , dcSessionFromMTProto (cfg .ThisDC , s ))
return nil
}
func (c *Client ) storeDCSess (target map [int ]*pool .SyncSession , data pool .Session ) {
c .sessionsMux .Lock ()
if existing , ok := target [data .DC ]; ok {
existing .Store (data )
c .sessionsMux .Unlock ()
return
}
target [data .DC ] = pool .NewSyncSession (data )
c .sessionsMux .Unlock ()
}
func dcSessionFromMTProto (dc int , s mtproto .Session ) pool .Session {
keyToStore := s .Key
if !s .PermKey .Zero () {
keyToStore = s .PermKey
}
return pool .Session {
DC : dc ,
Salt : s .Salt ,
AuthKey : keyToStore ,
}
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .