All checks were successful
Desktop source guards / guards (push) Successful in 6s
По логу ПК 01.10 каждая из 577 загрузок шла по новой сессии: ~1.8 с из 2.3 с уходило на открытие соединения через фронт (TCP, TLS, апгрейд WebSocket, проверка транспорта, соль). - Простаивающая файловая сессия живёт 75 с вместо 15 с, и на загрузке, и на отправке. Через туннель остаётся 15 с: там соединение и так открывается заново после каждого куска. - stopSession() искал upload-сессию по id без датацентра и не находил её: getSession() запускает такую сессию на основном DC. Две сессии оставались после первой отправки и переподключались каждые 93 с до конца работы (454 соединения на 8 отправок). - Сессия перед использованием временного ключа проверяет, что он всё ещё ключ своего DC. updateAuthKey() пропускает сессию, которая переподключается, и после смены маршрута между WEB-прокси и WSS один уничтоженный ключ отвергался у каждой сессии отдельно: загрузки стояли 20–30 с. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
197 lines
5.5 KiB
C++
197 lines
5.5 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#pragma once
|
|
|
|
#include "mtproto/details/mtproto_received_ids_manager.h"
|
|
#include "mtproto/protocol/mtproto_serialized_request.h"
|
|
#include "mtproto/auth/mtproto_auth_key.h"
|
|
#include "mtproto/session/private/auth_factory.h"
|
|
#include "mtproto/session/private/connection_factory.h"
|
|
#include "mtproto/session/private/message_handler.h"
|
|
#include "mtproto/session/private/transport.h"
|
|
#include "mtproto/session/session_delegate.h"
|
|
#include "mtproto/session/session_role.h"
|
|
#include "mtproto/session/session_state.h"
|
|
|
|
namespace MTP {
|
|
|
|
class Instance;
|
|
class RuntimeEnvironment;
|
|
enum class ProxyDiagnosticsPhase;
|
|
enum class ProxyDiagnosticsSeverity;
|
|
|
|
namespace details {
|
|
|
|
class AbstractConnection;
|
|
class SessionData;
|
|
class SessionDelegate;
|
|
class RSAPublicKey;
|
|
struct SessionOptions;
|
|
|
|
class SessionPrivate final : public QObject {
|
|
public:
|
|
SessionPrivate(
|
|
not_null<Instance*> instance,
|
|
not_null<SessionDelegate*> delegate,
|
|
not_null<QThread*> thread,
|
|
std::shared_ptr<SessionData> data,
|
|
ShiftedDcId shiftedDcId,
|
|
SessionRole role,
|
|
uint64 proxyGeneration = 0,
|
|
not_null<SessionConnectionFactory*> connectionFactory
|
|
= &DefaultSessionConnectionFactory(),
|
|
not_null<SessionAuthKeyFactory*> authKeyFactory
|
|
= &DefaultSessionAuthKeyFactory());
|
|
~SessionPrivate();
|
|
|
|
[[nodiscard]] int32 getShiftedDcId() const;
|
|
void dcOptionsChanged();
|
|
void cdnConfigChanged();
|
|
|
|
[[nodiscard]] int32 getState() const;
|
|
[[nodiscard]] QString transport() const;
|
|
|
|
void updateAuthKey();
|
|
void restartNow();
|
|
void migrateProxy(uint64 generation);
|
|
void sendPingForce();
|
|
void tryToSend();
|
|
|
|
private:
|
|
friend class SessionTransport;
|
|
friend class SessionMessageHandler;
|
|
|
|
static constexpr auto kUpdateStateAlways = 666;
|
|
|
|
struct SentContainer {
|
|
crl::time sent = 0;
|
|
std::vector<mtpMsgId> messages;
|
|
};
|
|
|
|
void connectToServer(bool afterConfig = false);
|
|
void doDisconnect();
|
|
void restart();
|
|
void onSentSome(uint64 size);
|
|
void onReceivedSome();
|
|
|
|
void handleReceived();
|
|
|
|
void sendPingByTimer();
|
|
void setConnectionNotice(ConnectionNotice notice);
|
|
void reportPingTime(crl::time time);
|
|
void logMtprotoEvent(
|
|
ProxyDiagnosticsPhase phase,
|
|
ProxyDiagnosticsSeverity severity,
|
|
const QString &message) const;
|
|
[[nodiscard]] QString mtprotoLogDc() const;
|
|
[[nodiscard]] int16 getProtocolDcId() const;
|
|
|
|
void checkSentRequests();
|
|
|
|
mtpMsgId placeToContainer(
|
|
SerializedRequest &toSendRequest,
|
|
mtpMsgId &bigMsgId,
|
|
bool forceNewMsgId,
|
|
SerializedRequest &req);
|
|
mtpMsgId prepareToSend(
|
|
SerializedRequest &request,
|
|
mtpMsgId currentLastId,
|
|
bool forceNewMsgId);
|
|
mtpMsgId replaceMsgId(
|
|
SerializedRequest &request,
|
|
mtpMsgId newId);
|
|
mtpMsgId RegisterSentRequest(
|
|
base::flat_map<mtpMsgId, SerializedRequest> &haveSent,
|
|
SerializedRequest &request,
|
|
mtpMsgId msgId);
|
|
|
|
bool sendSecureRequest(
|
|
SerializedRequest &&request,
|
|
bool needAnyResponse);
|
|
mtpRequestId wasSent(mtpMsgId msgId) const;
|
|
|
|
bool setState(int state, int ifState = kUpdateStateAlways);
|
|
|
|
[[nodiscard]] DcType tryAcquireKeyCreation();
|
|
void resetSession();
|
|
void checkAuthKey();
|
|
void authKeyChecked();
|
|
void destroyTemporaryKey();
|
|
void clearUnboundKeyCreator();
|
|
void releaseKeyCreationOnFail();
|
|
void applyAuthKey(AuthKeyPtr &&encryptionKey);
|
|
[[nodiscard]] bool noMediaKeyWithExistingRegularKey() const;
|
|
void dropMismatchedTemporaryKey();
|
|
void dropForgottenTemporaryKey();
|
|
bool destroyOldEnoughPersistentKey();
|
|
|
|
void setCurrentKeyId(uint64 newKeyId);
|
|
void changeSessionId();
|
|
[[nodiscard]] bool markSessionAsStarted();
|
|
[[nodiscard]] uint32 nextRequestSeqNumber(bool needAck);
|
|
|
|
[[nodiscard]] bool realDcTypeChanged();
|
|
[[nodiscard]] MTPVector<MTPJSONObjectValue> prepareInitParams();
|
|
|
|
struct RequestState {
|
|
mtpPingId pingId = 0;
|
|
mtpPingId pingIdToSend = 0;
|
|
crl::time pingSendAt = 0;
|
|
crl::time pingSentTime = 0;
|
|
mtpMsgId pingMsgId = 0;
|
|
QVector<MTPlong> ackData;
|
|
QVector<MTPlong> resendData;
|
|
base::flat_set<mtpMsgId> stateData;
|
|
ReceivedIdsManager receivedIds;
|
|
base::flat_map<mtpMsgId, mtpRequestId> resendingIds;
|
|
base::flat_map<mtpMsgId, mtpRequestId> ackedIds;
|
|
base::flat_map<mtpMsgId, SerializedRequest> stateAndResendRequests;
|
|
base::flat_map<mtpMsgId, SentContainer> sentContainers;
|
|
};
|
|
struct SessionState {
|
|
explicit SessionState(std::shared_ptr<SessionData> data);
|
|
|
|
std::shared_ptr<SessionData> data;
|
|
std::unique_ptr<SessionOptions> options;
|
|
AuthKeyPtr encryptionKey;
|
|
uint64 keyId = 0;
|
|
uint64 sessionId = 0;
|
|
uint64 sessionSalt = 0;
|
|
uint32 messagesCounter = 0;
|
|
bool markedAsStarted = false;
|
|
bool needReset = false;
|
|
};
|
|
struct AuthState {
|
|
std::unique_ptr<SessionBoundKeyCreator> keyCreator;
|
|
mtpMsgId bindMsgId = 0;
|
|
crl::time bindMessageSent = 0;
|
|
};
|
|
|
|
const not_null<Instance*> _instance;
|
|
const not_null<SessionDelegate*> _delegate;
|
|
const not_null<RuntimeEnvironment*> _runtime;
|
|
const not_null<SessionConnectionFactory*> _connectionFactory;
|
|
const not_null<SessionAuthKeyFactory*> _authKeyFactory;
|
|
const ShiftedDcId _shiftedDcId = 0;
|
|
const SessionRole _role = SessionRole::Auxiliary;
|
|
DcType _realDcType = DcType();
|
|
DcType _currentDcType = DcType();
|
|
|
|
mutable QReadWriteLock _stateMutex;
|
|
int _state = DisconnectedState;
|
|
|
|
SessionTransport _transport;
|
|
SessionMessageHandler _messageHandler;
|
|
RequestState _requestState;
|
|
SessionState _sessionState;
|
|
AuthState _authState;
|
|
|
|
};
|
|
|
|
} // namespace details
|
|
} // namespace MTP
|