-
-
Notifications
You must be signed in to change notification settings - Fork 128
/
connect.go
82 lines (69 loc) · 1.81 KB
/
connect.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
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
}