// Package exchange contains Telegram key exchange algorithm flows. // See https://core.telegram.org/mtproto/auth_key. package exchange import ( "io" "time" "go.uber.org/zap" "github.com/gotd/td/clock" "github.com/gotd/td/internal/crypto" "github.com/gotd/td/internal/proto" "github.com/gotd/td/transport" ) // DefaultTimeout is default WithTimeout parameter value. const DefaultTimeout = 1 * time.Minute // Exchanger is builder for key exchangers. type Exchanger struct { conn transport.Conn clock clock.Clock rand io.Reader log *zap.Logger timeout time.Duration dc int } // WithClock sets exchange flow clock. func (e Exchanger) WithClock(c clock.Clock) Exchanger { e.clock = c return e } // WithRand sets exchange flow random source. func (e Exchanger) WithRand(reader io.Reader) Exchanger { e.rand = reader return e } // WithLogger sets exchange flow logger. func (e Exchanger) WithLogger(log *zap.Logger) Exchanger { e.log = log return e } // WithTimeout sets write/read deadline of every exchange request. func (e Exchanger) WithTimeout(timeout time.Duration) Exchanger { e.timeout = timeout return e } // NewExchanger creates new Exchanger. func NewExchanger(conn transport.Conn, dc int) Exchanger { return Exchanger{ conn: conn, clock: clock.System, rand: crypto.DefaultRand(), log: zap.NewNop(), timeout: DefaultTimeout, dc: dc, } } func (e Exchanger) unencryptedWriter(input, output proto.MessageType) unencryptedWriter { return unencryptedWriter{ clock: e.clock, conn: e.conn, timeout: e.timeout, input: input, output: output, } } // Client creates new ClientExchange using parameters from Exchanger. func (e Exchanger) Client(keys []PublicKey) ClientExchange { return ClientExchange{ unencryptedWriter: e.unencryptedWriter( proto.MessageServerResponse, proto.MessageFromClient, ), rand: e.rand, log: e.log, keys: keys, dc: e.dc, } } // Server creates new ServerExchange using parameters from Exchanger. func (e Exchanger) Server(key PrivateKey) ServerExchange { return ServerExchange{ unencryptedWriter: e.unencryptedWriter( proto.MessageFromClient, proto.MessageServerResponse, ), rand: e.rand, log: e.log, rng: TestServerRNG{rand: e.rand}, key: key, dc: e.dc, } }