Some checks failed
ZaStoGram source guards / guards (push) Failing after 26s
Build three ZaStoGram APKs / build (arm64-v8a, ZaStoGram-standalone-arm64-v8a, Arm64, arm64) (push) Failing after 1m59s
Build three ZaStoGram APKs / build (x86, ZaStoGram-standalone-x86, X86, x86) (push) Failing after 2m5s
Build three ZaStoGram APKs / build (armeabi-v7a, ZaStoGram-standalone-armeabi-v7a, Armv7, armv7) (push) Failing after 2m9s
logs (11): ни один из 48 стикеров DC1 не догрузился. Загрузки стартовали до отключения релея с частями 32–128 КБ, которые через туннель не проходят никогда, а соединение туннеля пересоздавалось посреди такого ответа и слало его заново по кругу; зависания на них отключили туннель. Сеть сообщает Java, когда медиа-DC уходит в туннель, и идущие загрузки этого DC продолжают с уже скачанного частями по 8 КБ. Туннель пересоздаётся только между пакетами, а зависание посреди слишком большого ответа не засчитывается туннелю.
335 lines
15 KiB
C++
335 lines
15 KiB
C++
/*
|
||
* This is the source code of tgnet library v. 1.1
|
||
* It is licensed under GNU GPL v. 2 or later.
|
||
* You should have received a copy of the license in this archive (see LICENSE).
|
||
*
|
||
* Copyright Nikolai Kudashov, 2015-2018.
|
||
*/
|
||
|
||
#ifndef CONNECTIONSMANAGER_H
|
||
#define CONNECTIONSMANAGER_H
|
||
|
||
#include <pthread.h>
|
||
#include <queue>
|
||
#include <functional>
|
||
#include <memory>
|
||
#include <cstdint>
|
||
#include <sys/epoll.h>
|
||
#include <map>
|
||
#include <atomic>
|
||
#include <unordered_set>
|
||
#include <vector>
|
||
#include "Defines.h"
|
||
#include "mtproxy/MtProxyOptions.h"
|
||
|
||
#ifdef ANDROID
|
||
#include <jni.h>
|
||
#endif
|
||
|
||
class NativeByteBuffer;
|
||
class Connection;
|
||
class Datacenter;
|
||
class Request;
|
||
class DatacenterHandshake;
|
||
class TLObject;
|
||
class ConnectionSocket;
|
||
class TL_auth_exportedAuthorization;
|
||
class ByteArray;
|
||
class TL_config;
|
||
class EventObject;
|
||
|
||
namespace tgnet {
|
||
namespace wss {
|
||
class Pool;
|
||
struct Route;
|
||
class Socket;
|
||
}
|
||
}
|
||
class Config;
|
||
class ProxyCheckInfo;
|
||
|
||
class ConnectionsManager {
|
||
|
||
public:
|
||
ConnectionsManager(int32_t instance);
|
||
~ConnectionsManager();
|
||
|
||
static ConnectionsManager &getInstance(int32_t instanceNum);
|
||
int64_t getCurrentTimeMillis();
|
||
int64_t getCurrentTimeMonotonicMillis();
|
||
int32_t getCurrentTime();
|
||
int32_t getCurrentPingTime();
|
||
uint32_t getCurrentDatacenterId();
|
||
int64_t getCurrentAuthKeyId();
|
||
bool isTestBackend();
|
||
int32_t getTimeDifference();
|
||
int32_t sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, onRequestClearFunc onClear, uint32_t flags, uint32_t datacenterId, ConnectionType connectionType, bool immediate);
|
||
int32_t sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, onRequestClearFunc onClear, uint32_t flags, uint32_t datacenterId, ConnectionType connectionType, bool immediate, int32_t requestToken);
|
||
void cancelRequest(int32_t token, bool notifyServer, onRequestCancelDoneFunc onCancelled);
|
||
void cleanUp(bool resetKeys, int32_t datacenterId);
|
||
void cancelRequestsForGuid(int32_t guid);
|
||
void bindRequestToGuid(int32_t requestToken, int32_t guid);
|
||
void applyDatacenterAddress(uint32_t datacenterId, std::string ipAddress, uint32_t port);
|
||
void setDelegate(ConnectiosManagerDelegate *connectiosManagerDelegate);
|
||
ConnectionState getConnectionState();
|
||
void setUserId(int64_t userId);
|
||
void setUserPremium(bool premium);
|
||
void switchBackend(bool restart);
|
||
void resumeNetwork(bool partial);
|
||
void pauseNetwork();
|
||
void setNetworkAvailable(bool value, int32_t type, bool slow);
|
||
void setIpStrategy(uint8_t value);
|
||
void init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string systemLangCode, std::string configPath, std::string logPath, std::string regId, std::string cFingerprint, std::string installerId, std::string packageId, int32_t timezoneOffset, int64_t userId, bool userPremium, bool isPaused, bool enablePushConnection, bool hasNetwork, int32_t networkType, int32_t performanceClass);
|
||
void setProxySettings(std::string address, uint16_t port, std::string username, std::string password, std::string secret, const MtProxyOptions &options, uint32_t activationGeneration, std::string activationOrigin);
|
||
void setProxyActivationContext(uint32_t activationGeneration, std::string activationOrigin);
|
||
uint32_t getProxyActivationGeneration();
|
||
uint32_t getProxyConfigGeneration();
|
||
std::string getProxyActivationOrigin();
|
||
void setWssTransportEnabled(bool enabled);
|
||
bool isDatacenterTunneled(uint32_t datacenterId, bool media);
|
||
void setLangCode(std::string langCode);
|
||
void setRegId(std::string regId);
|
||
void setSystemLangCode(std::string langCode);
|
||
void updateDcSettings(uint32_t datacenterId, bool workaround, bool ifLoadingTryAgain);
|
||
void setPushConnectionEnabled(bool value);
|
||
void setLivePingInterval(int32_t intervalMs);
|
||
void applyDnsConfig(NativeByteBuffer *buffer, std::string phone, int32_t date);
|
||
int64_t checkProxy(std::string address, uint16_t port, std::string username, std::string password, std::string secret, const MtProxyOptions &options, onRequestTimeFunc requestTimeFunc, jobject ptr1);
|
||
void cancelProxyCheck(int64_t pingId);
|
||
void cancelProxyEndpointAttempts(std::string endpointKey, std::string probeKey, std::string reason);
|
||
|
||
#ifdef ANDROID
|
||
void sendRequest(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, onWriteToSocketFunc onWriteToSocket, onRequestClearFunc onClear, uint32_t flags, uint32_t datacenterId, ConnectionType connectionType, bool immediate, int32_t requestToken);
|
||
static void useJavaVM(JavaVM *vm, bool useJavaByteBuffers);
|
||
#endif
|
||
|
||
void reconnect(int32_t datacentrId, int32_t connectionType);
|
||
void failNotRunningRequest(int32_t token);
|
||
void receivedIntegrityCheckClassic(int32_t requestToken, std::string nonce, std::string token);
|
||
void receivedCaptchaResult(int32_t requestTokensCount, int32_t* requestTokens, std::string token);
|
||
void moveToDatacenter(uint32_t datacenterId);
|
||
void collectConnectionDiagnosticsAsync(uint32_t datacenterId, std::function<void(std::string)> completion);
|
||
|
||
private:
|
||
static void *ThreadProc(void *data);
|
||
|
||
void initDatacenters();
|
||
void loadConfig();
|
||
void saveConfig();
|
||
void saveConfigInternal(NativeByteBuffer *buffer);
|
||
void select();
|
||
void wakeup();
|
||
void processServerResponse(TLObject *message, int64_t messageId, int32_t messageSeqNo, int64_t messageSalt, Connection *connection, int64_t innerMsgId, int64_t containerMessageId);
|
||
void sendPing(Datacenter *datacenter, bool usePushConnection);
|
||
bool sendMessagesToConnection(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck, bool requeueOnDeadConnection = true);
|
||
bool sendMessagesToConnectionWithConfirmation(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck, bool requeueOnDeadConnection = true);
|
||
void requeueMessagesForDeadConnection(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, const char *reason);
|
||
void removeQuickAckMappingForMessages(int32_t quickAckId, const std::vector<std::unique_ptr<NetworkMessage>> &messages);
|
||
void requestSaltsForDatacenter(Datacenter *datacenter, bool media, bool useTempConnection);
|
||
void clearRequestsForDatacenter(Datacenter *datacenter, HandshakeType type);
|
||
void registerForInternalPushUpdates();
|
||
void processRequestQueue(uint32_t connectionType, uint32_t datacenterId);
|
||
void authorizeOnMovingDatacenter();
|
||
void authorizedOnMovingDatacenter();
|
||
Datacenter *getDatacenterWithId(uint32_t datacenterId);
|
||
std::unique_ptr<TLObject> wrapInLayer(TLObject *object, Datacenter *datacenter, Request *baseRequest);
|
||
void removeRequestFromGuid(int32_t requestToken);
|
||
bool cancelRequestInternal(int32_t token, int64_t messageId, bool notifyServer, bool removeFromClass, onRequestCancelDoneFunc onCancelled);
|
||
int callEvents(int64_t now);
|
||
int32_t sendRequestInternal(TLObject *object, onCompleteFunc onComplete, onQuickAckFunc onQuickAck, onRequestClearFunc onClear, uint32_t flags, uint32_t datacenterId, ConnectionType connetionType, bool immediate);
|
||
|
||
void checkPendingTasks();
|
||
void scheduleTask(std::function<void()> task);
|
||
void scheduleEvent(EventObject *eventObject, uint32_t time);
|
||
void removeEvent(EventObject *eventObject);
|
||
void onConnectionClosed(Connection *connection, int reason);
|
||
void onConnectionConnected(Connection *connection);
|
||
void onConnectionQuickAckReceived(Connection *connection, int32_t ack);
|
||
void onConnectionDataReceived(Connection *connection, NativeByteBuffer *data, uint32_t length);
|
||
bool hasPendingRequestsForConnection(Connection *connection);
|
||
void attachConnection(ConnectionSocket *connection);
|
||
void detachConnection(ConnectionSocket *connection);
|
||
std::string collectConnectionDiagnostics(uint32_t datacenterId);
|
||
bool shouldDebounceTransportSettingsReconnect(int64_t now);
|
||
void requestTransportSettingsReconnect(const char *reason);
|
||
void applyTransportSettingsReconnect(const char *reason);
|
||
TLObject *TLdeserialize(TLObject *request, uint32_t bytes, NativeByteBuffer *data);
|
||
TLObject *getRequestWithMessageId(int64_t messageId);
|
||
void onDatacenterHandshakeComplete(Datacenter *datacenter, HandshakeType type, int32_t timeDiff);
|
||
void onDatacenterExportAuthorizationComplete(Datacenter *datacenter);
|
||
int64_t generateMessageId();
|
||
uint8_t getIpStratagy();
|
||
bool isNetworkAvailable();
|
||
|
||
void scheduleCheckProxyInternal(ProxyCheckInfo *proxyCheckInfo);
|
||
void checkProxyInternal(ProxyCheckInfo *proxyCheckInfo);
|
||
void failProxyCheckStart(ProxyCheckInfo *proxyCheckInfo, const char *reason);
|
||
bool isProxyCheckRequestActive(int32_t requestToken);
|
||
bool eraseProxyCheckRequest(int32_t requestToken, int64_t *requestTime);
|
||
void finishProxyCheck(std::vector<std::unique_ptr<ProxyCheckInfo>>::iterator iter, int64_t time, const char *reason, const char *diagnostic, Connection *connection, bool notifyCallback);
|
||
void scheduleNextProxyCheck();
|
||
|
||
int32_t instanceNum = 0;
|
||
uint32_t configVersion = 5;
|
||
Config *config = nullptr;
|
||
|
||
std::list<EventObject *> events;
|
||
|
||
std::map<uint32_t, Datacenter *> datacenters;
|
||
// Троттлинг записи о запросах, ждущих ключ датацентра: состояние статичное,
|
||
// а очередь перебирается на каждом проходе цикла событий.
|
||
struct NoAuthKeyLogWindow {
|
||
int64_t lastLogTime = 0;
|
||
uint32_t suppressed = 0;
|
||
};
|
||
std::map<uint32_t, NoAuthKeyLogWindow> noAuthKeyLogWindows;
|
||
std::map<int32_t, std::vector<std::int32_t>> quickAckIdToRequestIds;
|
||
int32_t pingTime;
|
||
int64_t pingTimeMs;
|
||
bool testBackend = false;
|
||
bool clientBlocked = true;
|
||
std::string lastInitSystemLangcode = "";
|
||
std::atomic<uint32_t> lastRequestToken{50000000};
|
||
uint32_t currentDatacenterId = 0;
|
||
uint32_t movingToDatacenterId = DEFAULT_DATACENTER_ID;
|
||
int64_t pushSessionId = 0;
|
||
int32_t currentPingTime = 0;
|
||
int32_t currentPingTimeLive = 0;
|
||
int32_t livePingIntervalOverride = 0;
|
||
bool registeringForPush = false;
|
||
int64_t lastPushPingTime = 0;
|
||
int64_t lastProbeReapMs = 0;
|
||
std::unique_ptr<tgnet::wss::Pool> wssPool;
|
||
int64_t lastWssPoolTickMs = 0;
|
||
uint32_t tunneledMediaDatacenters = 0;
|
||
std::unique_ptr<tgnet::wss::Socket> takePooledWssSocket(const tgnet::wss::Route &route);
|
||
int32_t nextPingTimeOffset = 60000 * 3;
|
||
int64_t sendingPushPingTime = 0;
|
||
bool sendingPushPing = false;
|
||
bool sendingPing = false;
|
||
bool updatingDcSettings = false;
|
||
bool updatingDcSettingsAgain = false;
|
||
uint32_t updatingDcSettingsAgainDcNum = 0;
|
||
bool updatingDcSettingsWorkaround = false;
|
||
int32_t disconnectTimeoutAmount = 0;
|
||
bool requestingSecondAddressByTlsHashMismatch = false;
|
||
int32_t requestingSecondAddress = 0;
|
||
int32_t updatingDcStartTime = 0;
|
||
int32_t lastDcUpdateTime = 0;
|
||
int64_t lastPingTime = getCurrentTimeMonotonicMillis();
|
||
bool networkPaused = false;
|
||
int32_t nextSleepTimeout = CONNECTION_BACKGROUND_KEEP_TIME;
|
||
int64_t lastPauseTime = 0;
|
||
int64_t lastMonotonicPauseTime = 0;
|
||
int32_t lastSystemPauseTime = 0;
|
||
ConnectionState connectionState = ConnectionStateConnecting;
|
||
std::unique_ptr<ByteArray> movingAuthorization;
|
||
std::vector<int64_t> sessionsToDestroy;
|
||
int32_t lastDestroySessionRequestTime;
|
||
std::map<int32_t, std::vector<int32_t>> requestsByGuids;
|
||
std::map<int32_t, int32_t> guidsByRequests;
|
||
std::map<int64_t, int64_t> resendRequests;
|
||
Datacenter *deserializingDatacenter;
|
||
|
||
std::string proxyUser = "";
|
||
std::string proxyPassword = "";
|
||
std::string proxyAddress = "";
|
||
std::string proxySecret = "";
|
||
uint16_t proxyPort = 1080;
|
||
MtProxyOptions proxyMtProxyOptions;
|
||
uint32_t proxyActivationGeneration = 0;
|
||
uint32_t proxyConfigGeneration = 0;
|
||
std::string proxyActivationOrigin = "active_socket";
|
||
bool wssEnabled = false;
|
||
// Set once any connection has chosen its transport; before that a WSS
|
||
// toggle has nothing to reconnect.
|
||
bool transportConnectionOpened = false;
|
||
int64_t transportSettingsStartupSettleUntil = 0;
|
||
bool transportSettingsReconnectPending = false;
|
||
int32_t lastPingProxyId = 2000000;
|
||
std::vector<std::unique_ptr<ProxyCheckInfo>> proxyCheckQueue;
|
||
std::vector<std::unique_ptr<ProxyCheckInfo>> proxyActiveChecks;
|
||
|
||
pthread_t networkThread;
|
||
pthread_mutex_t mutex;
|
||
std::queue<std::function<void()>> pendingTasks;
|
||
struct epoll_event *epollEvents;
|
||
timespec timeSpec;
|
||
timespec timeSpecMonotonic;
|
||
int32_t timeDifference = 0;
|
||
int64_t lastOutgoingMessageId = 0;
|
||
bool networkAvailable = true;
|
||
bool networkSlow = false;
|
||
uint8_t ipStrategy = USE_IPV4_ONLY;
|
||
bool lastProtocolIsIpv6 = false;
|
||
bool lastProtocolUsefullData = false;
|
||
std::vector<ConnectionSocket *> activeConnections;
|
||
std::vector<ConnectionSocket *> activeConnectionsCopy;
|
||
std::map<uint32_t, std::string> recentConnectionDiagnostics;
|
||
int epolFd;
|
||
int eventFd;
|
||
int *pipeFd = nullptr;
|
||
NativeByteBuffer *networkBuffer;
|
||
|
||
requestsList waitingLoginRequests;
|
||
requestsList requestsQueue;
|
||
requestsList runningRequests;
|
||
std::vector<uint32_t> requestingSaltsForDc;
|
||
std::unordered_set<int32_t> tokensToBeCancelled;
|
||
int32_t lastPingId = 0;
|
||
int64_t lastInvokeAfterMessageId = 0;
|
||
|
||
int32_t currentNetworkType = NETWORK_TYPE_WIFI;
|
||
uint32_t currentVersion = 1;
|
||
int32_t currentLayer = 34;
|
||
int32_t currentApiId = 6;
|
||
std::string currentDeviceModel;
|
||
std::string currentSystemVersion;
|
||
std::string currentAppVersion;
|
||
std::string currentLangCode;
|
||
std::string currentRegId;
|
||
std::string certFingerprint;
|
||
std::string installer;
|
||
std::string package;
|
||
int32_t currentDeviceTimezone = 0;
|
||
std::string currentSystemLangCode;
|
||
std::string currentConfigPath;
|
||
std::string currentLogPath;
|
||
int64_t currentUserId = 0;
|
||
bool currentUserPremium = false;
|
||
bool registeredForInternalPush = false;
|
||
bool pushConnectionEnabled = true;
|
||
int32_t currentPerformanceClass = -1;
|
||
|
||
std::map<uint32_t, std::vector<std::unique_ptr<NetworkMessage>>> genericMessagesToDatacenters;
|
||
std::map<uint32_t, std::vector<std::unique_ptr<NetworkMessage>>> genericMediaMessagesToDatacenters;
|
||
std::map<uint32_t, std::vector<std::unique_ptr<NetworkMessage>>> tempMessagesToDatacenters;
|
||
std::vector<uint32_t> unknownDatacenterIds;
|
||
std::vector<std::pair<Datacenter *, ConnectionType>> neededDatacenters;
|
||
std::map<uint32_t, uint32_t> downloadRunningRequestCount;
|
||
std::map<uint32_t, uint32_t> downloadCancelRunningRequestCount;
|
||
std::vector<Datacenter *> unauthorizedDatacenters;
|
||
NativeByteBuffer *sizeCalculator;
|
||
|
||
ConnectiosManagerDelegate *delegate;
|
||
|
||
friend class ConnectionSocket;
|
||
friend class ConnectionSession;
|
||
friend class Connection;
|
||
friend class Timer;
|
||
friend class Datacenter;
|
||
friend class TL_message;
|
||
friend class TL_rpc_result;
|
||
friend class Config;
|
||
friend class FileLog;
|
||
friend class Handshake;
|
||
};
|
||
|
||
#ifdef ANDROID
|
||
extern JavaVM *javaVm;
|
||
extern JNIEnv *jniEnv[MAX_ACCOUNT_COUNT];
|
||
extern jclass jclass_ByteBuffer;
|
||
extern jmethodID jclass_ByteBuffer_allocateDirect;
|
||
#endif
|
||
|
||
#endif
|