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.
82 lines
1.8 KiB
82 lines
1.8 KiB
package mtproto |
|
|
|
import ( |
|
"context" |
|
|
|
"github.com/go-faster/errors" |
|
"go.uber.org/multierr" |
|
"go.uber.org/zap" |
|
|
|
"github.com/gotd/td/internal/exchange" |
|
) |
|
|
|
// connect establishes connection using configured transport, creating |
|
// new auth key if needed. |
|
func (c *Conn) connect(ctx context.Context) (rErr error) { |
|
ctx, cancel := context.WithTimeout(ctx, c.dialTimeout) |
|
defer cancel() |
|
|
|
conn, err := c.dialer(ctx) |
|
if err != nil { |
|
return errors.Wrap(err, "dial failed") |
|
} |
|
c.conn = conn |
|
defer func() { |
|
if rErr != nil { |
|
multierr.AppendInto(&rErr, conn.Close()) |
|
} |
|
}() |
|
|
|
session := c.session() |
|
if session.Key.Zero() { |
|
c.log.Info("Generating new auth key") |
|
start := c.clock.Now() |
|
if err := c.createAuthKey(ctx); err != nil { |
|
return errors.Wrap(err, "create auth key") |
|
} |
|
|
|
c.log.Info("Auth key generated", |
|
zap.Duration("duration", c.clock.Now().Sub(start)), |
|
) |
|
return nil |
|
} |
|
|
|
c.log.Info("Key already exists") |
|
if session.ID == 0 { |
|
// NB: Telegram can return 404 error if session id is zero. |
|
// |
|
// See https://github.com/gotd/td/issues/107. |
|
c.log.Debug("Generating new session id") |
|
if err := c.newSessionID(); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// createAuthKey generates new authorization key. |
|
func (c *Conn) createAuthKey(ctx context.Context) error { |
|
// Grab exclusive lock for writing. |
|
// It prevents message sending during key regeneration if server forgot current auth key. |
|
c.exchangeLock.Lock() |
|
defer c.exchangeLock.Unlock() |
|
|
|
r, err := exchange.NewExchanger(c.conn, c.dcID). |
|
WithClock(c.clock). |
|
WithLogger(c.log.Named("exchange")). |
|
WithTimeout(c.exchangeTimeout). |
|
WithRand(c.rand). |
|
Client(c.rsaPublicKeys).Run(ctx) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
c.sessionMux.Lock() |
|
c.authKey = r.AuthKey |
|
c.sessionID = r.SessionID |
|
c.salt = r.ServerSalt |
|
c.sessionMux.Unlock() |
|
|
|
return nil |
|
}
|
|
|