Documentation
¶
Overview ¶
Package mtproto implements MTProto connection.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrPFSReconnectRequired is returned when connection should be recreated // to continue PFS flow (e.g. temp key renewal). ErrPFSReconnectRequired = errors.New("pfs reconnect required") // ErrPFSDropKeysRequired is returned when stored permanent key should be // dropped and generated again on the next connection attempt. ErrPFSDropKeysRequired = errors.New("pfs drop keys required") )
Functions ¶
This section is empty.
Types ¶
type Cipher ¶ added in v0.19.0
type Cipher interface {
DecryptFromBuffer(k crypto.AuthKey, buf *bin.Buffer) (*crypto.EncryptedMessageData, error)
Encrypt(key crypto.AuthKey, data crypto.EncryptedMessageData, b *bin.Buffer) error
}
Cipher handles message encryption and decryption.
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn represents a MTProto client to Telegram.
func (*Conn) Invoke ¶ added in v0.98.0
Invoke sends input and decodes result into output.
NOTE: Assuming that call contains content message (seqno increment).
type MessageBuf ¶ added in v0.98.0
MessageBuf is message id buffer.
type MessageIDSource ¶
type MessageIDSource interface {
New(t proto.MessageType) int64
}
MessageIDSource is message id generator.
type NewSessionHandler ¶
NewSessionHandler is implemented by a Handler that wants to know when the server created a new session (new_session_created), e.g. to recover updates it may have missed.
type Options ¶
type Options struct {
// DC is datacenter ID for key exchange.
// Defaults to 2.
DC int
// PublicKeys of telegram.
//
// If not provided, embedded public keys will be used.
PublicKeys []exchange.PublicKey
// Random is random source. Defaults to crypto.
Random io.Reader
// Logger is the structured logger. No logs by default.
Logger log.Logger
// Handler will be called on received message.
Handler Handler
// AckBatchSize is maximum ack-s to buffer.
AckBatchSize int
// AckInterval is maximum time to buffer ack.
AckInterval time.Duration
// RetryInterval is duration between retries.
RetryInterval time.Duration
// MaxRetries is max retry count until rpc request failure.
MaxRetries int
// DialTimeout is timeout of creating connection.
DialTimeout time.Duration
// ExchangeTimeout is timeout of every key exchange request.
ExchangeTimeout time.Duration
// SaltFetchInterval is the duration between get_future_salts requests.
//
// Zero (default) never sends get_future_salts, like Telegram Desktop:
// the server salt is taken from new_session_created and bad_server_salt
// (a request with an expired salt is re-sent with the new one). A
// positive value fetches future salts every interval, the first time
// one interval after the session starts.
SaltFetchInterval time.Duration
// PingTimeout is the time to wait for a pong, after which the connection
// is considered dead. Default is 15 seconds.
PingTimeout time.Duration
// PingInterval is the duration between ping_delay_disconnect requests.
//
// Zero (default) pings like Telegram Desktop: every 30–45 seconds (a
// random interval in [30s, 45s]) with disconnect_delay 60. A positive
// value pings at that fixed interval with disconnect_delay
// PingInterval + PingTimeout.
PingInterval time.Duration
// RequestTimeout is function which returns request timeout for given type ID.
RequestTimeout func(req uint32) time.Duration
// CompressThreshold is a threshold in bytes to determine that message
// is large enough to be compressed using GZIP.
// If < 0, compression will be disabled.
// If == 0, default value will be used.
CompressThreshold int
// MessageID is message id source. Share source between connection to
// reduce collision probability.
MessageID MessageIDSource
// Clock is current time source. Defaults to system time.
Clock clock.Clock
// ServerTime tracks the server time offset; share it between connections
// of a client. Defaults to a new ServerTime over Clock. Message ids of the
// default MessageID source and the msg_id time check use it.
ServerTime *ServerTime
// Types map, used in verbose logging of incoming message.
Types *tmap.Map
// Key that can be used to restore previous connection.
Key crypto.AuthKey
// PermKey is permanent auth key for PFS mode.
PermKey crypto.AuthKey
// Salt from server that can be used to restore previous connection.
Salt int64
// SessionState keeps the server session (session_id and seqno) across
// reconnects of a connection slot with the same key. Nil starts a new
// session on every connect. Not used in PFS mode, where every connection
// has a new temporary key.
SessionState *SessionState
// KeyCreatedAt is the creation time of the permanent key (Key, or PermKey
// in PFS mode), Unix seconds; zero if unknown. It is reported back in
// Session.KeyCreatedAt and used by the PFS key recovery policy.
KeyCreatedAt int64
// EnablePFS enables Perfect Forward Secrecy using temporary auth keys.
EnablePFS bool
// TempKeyTTL is temporary auth key lifetime in seconds.
// Default: 86400 (24h). Minimum: 60.
TempKeyTTL int
// Tracer for OTEL.
Tracer trace.Tracer
// WireTracer observes plaintext messages and lifecycle events of the
// connection. Nil (default) disables wire tracing.
WireTracer WireTracer
// Cipher defines message crypto.
Cipher Cipher
// contains filtered or unexported fields
}
Options of Conn.
type ServerTime ¶
type ServerTime struct {
// contains filtered or unexported fields
}
ServerTime tracks the difference between the server clock and the local clock, so that message ids and the msg_id time window use server time even when the local clock is off.
Like TDLib (AuthData::update_server_time_difference), the difference is taken from the time encoded in every received msg_id (and the server_time of the key exchange): the first observation sets it, later ones only raise it, since a message is always received after the server created it. A bad_msg_notification "msg_id too high" resets it from the notification's own msg_id.
One ServerTime is shared by all connections of a client. It is safe for concurrent use.
func NewServerTime ¶
func NewServerTime(base clock.Clock, offset time.Duration) *ServerTime
NewServerTime creates a ServerTime over the base clock (clock.System if nil), starting with the given offset, e.g. a persisted one. The offset is replaced by the first observed server time.
func (*ServerTime) Known ¶
func (t *ServerTime) Known() bool
Known reports whether the offset was observed from the server.
func (*ServerTime) Offset ¶
func (t *ServerTime) Offset() time.Duration
Offset returns server time minus local time.
func (*ServerTime) Seed ¶
func (t *ServerTime) Seed(offset time.Duration)
Seed sets the offset, e.g. one persisted by a previous run, unless it was already observed from the server.
type Session ¶
type Session struct {
ID int64
Key crypto.AuthKey
Salt int64
// PermKey is non-zero only in PFS mode and is used for bindTempAuthKey.
PermKey crypto.AuthKey
// KeyCreatedAt is the creation time of the permanent key (Key, or PermKey
// in PFS mode), Unix seconds; zero if unknown.
KeyCreatedAt int64
}
Session represents connection state.
type SessionState ¶
type SessionState struct {
// contains filtered or unexported fields
}
SessionState is the server session of a connection slot: session_id and the number of content messages sent in it (for seqno). Connections that share a SessionState one at a time continue the same server session after a reconnect with the same auth key, so the server keeps its queued answers and updates and does not send new_session_created, like TDLib and Telegram Desktop do. A new session is started when the key changes.
A SessionState must be used by one connection at a time: acquire it with TryAcquire before passing it in Options; the connection releases it when Run returns.
func NewSessionState ¶
func NewSessionState() *SessionState
NewSessionState returns an empty SessionState.
func (*SessionState) TryAcquire ¶
func (s *SessionState) TryAcquire() bool
TryAcquire marks the state as used by a connection. It reports false if another connection uses it.
type WireConn ¶
type WireConn struct {
// ID is unique for every Conn of the process, starting from 1.
ID int64
// DC is the DC id of the connection used for key exchange
// (Options.DC): 10000 is added for test DCs.
DC int
}
WireConn identifies the connection of a traced message or event.
type WireDirection ¶
type WireDirection uint8
WireDirection is the direction of a traced message.
const ( // WireOut is a message sent by the client. WireOut WireDirection = iota + 1 // WireIn is a message received from the server. WireIn )
Message directions.
func (WireDirection) String ¶
func (d WireDirection) String() string
String implements fmt.Stringer.
type WireEvent ¶
type WireEvent struct {
Type WireEventType
Conn WireConn
// AuthKeyID, TempKey and ExpiresAt (unix seconds, temporary keys only)
// describe the auth key of key events.
AuthKeyID [8]byte
TempKey bool
ExpiresAt int64
// Old and New are session ids or salts.
Old, New int64
MessageID int64
SeqNo int32
TypeID uint32
Latency time.Duration
Reason string
Err error
}
WireEvent is a connection lifecycle event. Fields are set depending on Type.
type WireEventType ¶
type WireEventType uint8
WireEventType is the type of a WireEvent.
const ( // WireConnStart is reported before dialing. WireConnStart WireEventType = iota + 1 // WireConnUp is reported when the transport connection is established. WireConnUp // WireConnDown is reported when the connection is closed, Err is the // reason (nil on graceful close). WireConnDown // WireKeyCreated is reported when a new auth key is created by key // exchange: AuthKeyID, TempKey and ExpiresAt (temporary keys). WireKeyCreated // WireKeySet is reported when the connection starts using an auth key // for messages, including after the key is re-created because the server // did not find it: AuthKeyID, TempKey and ExpiresAt (temporary keys). WireKeySet // WireSessionNew is reported when the client session id changes: // Old and New. WireSessionNew // WireSaltChange is reported when the server salt changes: Old and New. // Salts set by key exchange are implied by WireKeyCreated. WireSaltChange // WireDecryptFailed is reported when an incoming message can't be // decrypted or fails the msg_key check: Err. WireDecryptFailed // WireRejected is reported when a decrypted incoming message is // rejected: MessageID and Reason ("bad_session" or "bad_msg_id"). WireRejected // WireRequest is reported when a request is going to be sent: // MessageID, SeqNo and TypeID (of the encoded request, e.g. a // wrapper like invokeWithLayer). WireRequest // WireRequestResend is reported when a request is re-encoded and sent // again after bad_server_salt: MessageID and Reason ("bad_server_salt"). // Retransmits after an ack timeout reuse the message id and are only // visible as repeated outgoing messages. WireRequestResend // WireRequestDone is reported when a request is finished: MessageID, // Err (nil on success, RPC or context error otherwise) and Latency. WireRequestDone )
Event types.
func (WireEventType) String ¶
func (t WireEventType) String() string
String implements fmt.Stringer.
type WireMessage ¶
type WireMessage struct {
Conn WireConn
Direction WireDirection
// AuthKeyID is the id of the auth key the message is encrypted with.
AuthKeyID [8]byte
// TempKey is true if the message is encrypted with a temporary
// (PFS) key.
TempKey bool
Salt int64
SessionID int64
MessageID int64
SeqNo int32
}
WireMessage is the header of a traced message.
type WireTracer ¶
type WireTracer interface {
// OnMessage is called for every encrypted message: outgoing messages
// just before encryption and incoming messages after decryption and
// msg_key check, before session and msg_id checks (rejected messages
// are reported too, followed by a WireRejected event).
//
// The body is the serialized message body as sent or received
// (including gzip_packed and msg_container). It is only valid during
// the call: the tracer must not modify or retain it, and must copy it
// if needed.
OnMessage(m WireMessage, body []byte)
// OnEvent is called on connection, key, session and request lifecycle
// events.
OnEvent(e WireEvent)
}
WireTracer observes the plaintext MTProto traffic and the lifecycle of a connection, e.g. to record wire traces for debugging or for comparing the client behavior with other implementations.
Callbacks are called synchronously from the connection goroutines, so implementations must be safe for concurrent use and must return quickly.
Calls are not ordered by wire order: incoming messages are decrypted concurrently, and outgoing messages are reported by concurrent writers just before they are written, so a reported outgoing message may never reach the wire if the write fails. Order by message id where needed.
The tracer never receives auth key material: only auth key ids.
Source Files
¶
- ack.go
- bind.go
- conn.go
- connect.go
- doc.go
- handle_ack.go
- handle_bad_msg.go
- handle_container.go
- handle_future_salts.go
- handle_gzip.go
- handle_message.go
- handle_result.go
- handle_session_created.go
- http_wait.go
- message_id.go
- new_encrypted_msg.go
- options.go
- pfs.go
- ping.go
- read.go
- rpc.go
- salt.go
- server_time.go
- session.go
- session_state.go
- vendored_keys.go
- wire_tracer.go
- write.go
- zap.go