mtproto

package
v0.165.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 27 Imported by: 6

Documentation

Overview

Package mtproto implements MTProto connection.

Index

Constants

This section is empty.

Variables

View Source
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 New added in v0.18.0

func New(dialer Dialer, opt Options) *Conn

New creates new unstarted connection.

func (*Conn) Invoke added in v0.98.0

func (c *Conn) Invoke(ctx context.Context, input bin.Encoder, output bin.Decoder) error

Invoke sends input and decodes result into output.

NOTE: Assuming that call contains content message (seqno increment).

func (*Conn) Ping

func (c *Conn) Ping(ctx context.Context) error

Ping sends ping request to server and waits until pong is received or context is canceled.

func (*Conn) Run added in v0.18.0

func (c *Conn) Run(ctx context.Context, f func(ctx context.Context) error) (rErr error)

Run initializes MTProto connection to server and blocks until disconnection.

When connection is ready, Handler.OnSession is called.

type Dialer added in v0.98.0

type Dialer func(ctx context.Context) (transport.Conn, error)

Dialer is an abstraction for MTProto transport connection creator.

type Handler

type Handler interface {
	OnMessage(b *bin.Buffer) error
	OnSession(session Session) error
}

Handler will be called on received message from Telegram.

type MessageBuf added in v0.98.0

type MessageBuf interface {
	Consume(id int64) bool
}

MessageBuf is message id buffer.

type MessageIDSource

type MessageIDSource interface {
	New(t proto.MessageType) int64
}

MessageIDSource is message id generator.

type NewSessionHandler

type NewSessionHandler interface {
	OnNewSession(firstMsgID int64) error
}

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) Now

func (t *ServerTime) Now() time.Time

Now returns the current server time.

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.

Directories

Path Synopsis
Package salts contains MTProto server salt storage.
Package salts contains MTProto server salt storage.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL