Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,964 @@
/*
* 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 APISCHEME_H
#define APISCHEME_H
#include <vector>
#include <memory>
#include "TLObject.h"
class ByteArray;
class NativeByteBuffer;
class Bool : public TLObject {
public:
static Bool *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_boolTrue : public Bool {
public:
static const uint32_t constructor = 0x997275b5;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_boolFalse : public Bool {
public:
static const uint32_t constructor = 0xbc799737;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_dcOption : public TLObject {
public:
static const uint32_t constructor = 0x18b7a10d;
int32_t flags;
bool ipv6;
bool media_only;
bool tcpo_only;
bool cdn;
bool isStatic;
bool thisPortOnly;
bool force_try_ipv6;
int32_t id;
std::string ip_address;
int32_t port;
std::unique_ptr<ByteArray> secret;
static TL_dcOption *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_cdnPublicKey : public TLObject {
public:
static const uint32_t constructor = 0xc982eaba;
int32_t dc_id;
std::string public_key;
static TL_cdnPublicKey *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_cdnConfig : public TLObject {
public:
static const uint32_t constructor = 0x5725e40a;
std::vector<std::unique_ptr<TL_cdnPublicKey>> public_keys;
static TL_cdnConfig *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_help_getCdnConfig : public TLObject {
public:
static const uint32_t constructor = 0x52029342;
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class Reaction : public TLObject {
public:
static Reaction *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_config : public TLObject {
public:
static const uint32_t constructor = 0xcc1a241e;
int32_t flags;
int32_t date;
int32_t expires;
bool test_mode;
int32_t this_dc;
std::vector<std::unique_ptr<TL_dcOption>> dc_options;
std::string dc_txt_domain_name;
int32_t chat_size_max;
int32_t megagroup_size_max;
int32_t forwarded_count_max;
int32_t online_update_period_ms;
int32_t offline_blur_timeout_ms;
int32_t offline_idle_timeout_ms;
int32_t online_cloud_timeout_ms;
int32_t notify_cloud_delay_ms;
int32_t notify_default_delay_ms;
int32_t push_chat_period_ms;
int32_t push_chat_limit;
// int32_t saved_gifs_limit;
int32_t edit_time_limit;
int32_t revoke_time_limit;
int32_t revoke_pm_time_limit;
int32_t rating_e_decay;
int32_t stickers_recent_limit;
// int32_t stickers_faved_limit;
int32_t channels_read_media_period;
int32_t tmp_sessions;
// int32_t pinned_dialogs_count_max;
// int32_t pinned_infolder_count_max;
int32_t call_receive_timeout_ms;
int32_t call_ring_timeout_ms;
int32_t call_connect_timeout_ms;
int32_t call_packet_timeout_ms;
std::string me_url_prefix;
std::string autoupdate_url_prefix;
std::string gif_search_username;
std::string venue_search_username;
std::string img_search_username;
std::string static_maps_provider;
int32_t caption_length_max;
int32_t message_length_max;
int32_t webfile_dc_id;
std::string suggested_lang_code;
int32_t lang_pack_version;
int32_t base_lang_pack_version;
std::unique_ptr<Reaction> reactions_default;
std::string autologin_token;
static TL_config *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_help_getConfig : public TLObject {
public:
static const uint32_t constructor = 0xc4f9186b;
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_account_registerDevice : public TLObject {
public:
static const uint32_t constructor = 0x637ea878;
int32_t token_type;
std::string token;
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class UserStatus : public TLObject {
public:
int32_t expires;
static UserStatus *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_userStatusOffline : public UserStatus {
public:
static const uint32_t constructor = 0x8c703f;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusLastWeek : public UserStatus {
public:
static const uint32_t constructor = 0x7bf09fc;
uint32_t flags;
bool by_me;
void serializeToStream(NativeByteBuffer *stream);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_userStatusLastWeek_layer171 : public UserStatus {
public:
static const uint32_t constructor = 0x7bf09fc;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusEmpty : public UserStatus {
public:
static const uint32_t constructor = 0x9d05049;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusLastMonth : public UserStatus {
public:
static const uint32_t constructor = 0x65899777;
uint32_t flags;
bool by_me;
void serializeToStream(NativeByteBuffer *stream);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_userStatusLastMonth_layer171 : public UserStatus {
public:
static const uint32_t constructor = 0x77ebc742;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusOnline : public UserStatus {
public:
static const uint32_t constructor = 0xedb93949;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusRecently : public UserStatus {
public:
static const uint32_t constructor = 0x7b197dc8;
uint32_t flags;
bool by_me;
void serializeToStream(NativeByteBuffer *stream);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_userStatusRecently_layer171 : public UserStatus {
public:
static const uint32_t constructor = 0xe26f42f1;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userStatusHidden : public UserStatus {
public:
static const uint32_t constructor = 0xcf7d64b1;
void serializeToStream(NativeByteBuffer *stream);
};
class FileLocation : public TLObject {
public:
int64_t volume_id;
int32_t local_id;
static FileLocation *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_fileLocationToBeDeprecated : public FileLocation {
public:
static const uint32_t constructor = 0xbc7fc6cd;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class UserProfilePhoto : public TLObject {
public:
int32_t flags;
bool has_video;
int64_t photo_id;
std::unique_ptr<ByteArray> stripped_thumb;
int32_t dc_id;
static UserProfilePhoto *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_userProfilePhotoEmpty : public UserProfilePhoto {
public:
static const uint32_t constructor = 0x4f11bae1;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_userProfilePhoto : public UserProfilePhoto {
public:
static const uint32_t constructor = 0x82d1f706;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_restrictionReason : public TLObject {
public:
static const uint32_t constructor = 0xd072acb4;
std::string platform;
std::string reason;
std::string text;
static TL_restrictionReason *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_recentStory : public TLObject {
public:
static const uint32_t constructor = 0x711d692d;
int32_t flags;
bool is_live;
int32_t max_id;
static TL_recentStory *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_username : public TLObject {
public:
static const uint32_t constructor = 0xb4073647;
int32_t flags;
bool editable;
bool active;
std::string username;
static TL_username *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_peerColor : public TLObject {
public:
static const uint32_t constructor = 0xb54b5acf;
int32_t flags;
int32_t color;
int64_t background_emoji_id;
static TL_peerColor *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class EmojiStatus : public TLObject {
public:
static EmojiStatus *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_emojiStatusEmpty : public EmojiStatus {
public:
static const uint32_t constructor = 0xb54b5acf;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_emojiStatus : public EmojiStatus {
public:
static const uint32_t constructor = 0xe7ff068a;
int32_t flags;
int64_t document_id;
int32_t until;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_emojiStatus_layer197 : public EmojiStatus {
public:
static const uint32_t constructor = 0x929b619d;
int64_t document_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_emojiStatusUntil_layer197 : public EmojiStatus {
public:
static const uint32_t constructor = 0xfa30a8c7;
int64_t document_id;
int32_t until;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_emojiStatusCollectible : public EmojiStatus {
public:
static const uint32_t constructor = 0x7184603b;
int32_t flags;
int64_t collectible_id;
int64_t document_id;
std::string title;
std::string slug;
int64_t pattern_document_id;
int32_t center_color;
int32_t edge_color;
int32_t pattern_color;
int32_t text_color;
int32_t until;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class User : public TLObject {
public:
int64_t id;
std::string first_name;
std::string last_name;
std::string username;
int64_t access_hash;
std::string phone;
std::unique_ptr<UserProfilePhoto> photo;
std::unique_ptr<UserStatus> status;
int32_t flags;
int32_t flags2;
int32_t bot_info_version;
std::vector<std::unique_ptr<TL_restrictionReason>> restriction_reason;
std::string bot_inline_placeholder;
std::string lang_code;
std::vector<std::unique_ptr<TL_username>> usernames;
std::unique_ptr<TL_recentStory> stories_max_id;
std::unique_ptr<EmojiStatus> emoji_status;
std::unique_ptr<TL_peerColor> color;
std::unique_ptr<TL_peerColor> profile_color;
int32_t bot_active_users;
int64_t bot_verification_icon;
int64_t send_paid_messages_stars;
static User *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_userEmpty : public User {
public:
static const uint32_t constructor = 0x31774388;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_user : public User {
public:
static const uint32_t constructor = 0xd3bc4b7a;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_user_layer216 : public TL_user {
public:
static const uint32_t constructor = 0x20b1422;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class InputPeer : public TLObject {
public:
int64_t user_id;
int64_t chat_id;
int64_t channel_id;
int64_t access_hash;
static InputPeer *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_inputPeerSelf : public InputPeer {
public:
static const uint32_t constructor = 0x7da07ec9;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerUser : public InputPeer {
public:
static const uint32_t constructor = 0xdde8a54c;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerChat : public InputPeer {
public:
static const uint32_t constructor = 0x35a95cb9;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerUserFromMessage : public InputPeer {
public:
static const uint32_t constructor = 0xa87b0a1c;
std::unique_ptr<InputPeer> peer;
int32_t msg_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerChannelFromMessage : public InputPeer {
public:
static const uint32_t constructor = 0xbd2a0840;
std::unique_ptr<InputPeer> peer;
int32_t msg_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerChannel : public InputPeer {
public:
static const uint32_t constructor = 0x27bcbbfc;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputPeerEmpty : public InputPeer {
public:
static const uint32_t constructor = 0x7f3b18ea;
void serializeToStream(NativeByteBuffer *stream);
};
class InputUser : public TLObject {
public:
int64_t user_id;
int64_t access_hash;
static InputUser *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_inputUserSelf : public InputUser {
public:
static const uint32_t constructor = 0xf7c1b13f;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputUser : public InputUser {
public:
static const uint32_t constructor = 0xf21158c6;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputUserEmpty : public InputUser {
public:
static const uint32_t constructor = 0xb98886cf;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputUserFromMessage : public InputUser {
public:
static const uint32_t constructor = 0x1da448e2;
std::unique_ptr<InputPeer> peer;
int32_t msg_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class MessageEntity : public TLObject {
public:
int32_t flags;
int32_t offset;
int32_t length;
std::string url;
std::string language;
static MessageEntity *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_messageEntityTextUrl : public MessageEntity {
public:
static const uint32_t constructor = 0x76a6d327;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityBotCommand : public MessageEntity {
public:
static const uint32_t constructor = 0x6cef8ac7;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityEmail : public MessageEntity {
public:
static const uint32_t constructor = 0x64e475c2;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityPre : public MessageEntity {
public:
static const uint32_t constructor = 0x73924be0;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityUnknown : public MessageEntity {
public:
static const uint32_t constructor = 0xbb92ba95;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityUrl : public MessageEntity {
public:
static const uint32_t constructor = 0x6ed02538;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityItalic : public MessageEntity {
public:
static const uint32_t constructor = 0x826f8b60;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityMention : public MessageEntity {
public:
static const uint32_t constructor = 0xfa04579d;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityMentionName : public MessageEntity {
public:
static const uint32_t constructor = 0xdc7b1140;
int64_t user_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputMessageEntityMentionName : public MessageEntity {
public:
static const uint32_t constructor = 0x208e68c9;
std::unique_ptr<InputUser> user_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityCashtag : public MessageEntity {
public:
static const uint32_t constructor = 0x4c4e743f;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityBold : public MessageEntity {
public:
static const uint32_t constructor = 0xbd610bc9;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityHashtag : public MessageEntity {
public:
static const uint32_t constructor = 0x6f635b0d;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityCode : public MessageEntity {
public:
static const uint32_t constructor = 0x28a20571;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityStrike : public MessageEntity {
public:
static const uint32_t constructor = 0xbf0693d4;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityBlockquote : public MessageEntity {
public:
static const uint32_t constructor = 0xf1ccaaac;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityBlockquote_layer180 : public MessageEntity {
public:
static const uint32_t constructor = 0x20df5d0;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityUnderline : public MessageEntity {
public:
static const uint32_t constructor = 0x9c4e7e8b;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_messageEntityPhone : public MessageEntity {
public:
static const uint32_t constructor = 0x9b69e34b;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_dataJSON : public TLObject {
public:
static const uint32_t constructor = 0x7d748d04;
std::string data;
static TL_dataJSON *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_help_termsOfService : public TLObject {
public:
static const uint32_t constructor = 0x780a0310;
int32_t flags;
bool popup;
std::unique_ptr<TL_dataJSON> id;
std::string text;
std::vector<std::unique_ptr<MessageEntity>> entities;
int32_t min_age_confirm;
static TL_help_termsOfService *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class auth_Authorization : public TLObject {
public:
static auth_Authorization *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_auth_authorizationSignUpRequired : public auth_Authorization {
public:
static const uint32_t constructor = 0x44747e9a;
int32_t flags;
std::unique_ptr<TL_help_termsOfService> terms_of_service;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_auth_authorization : public auth_Authorization {
public:
static const uint32_t constructor = 0x2ea2c0d4;
int32_t flags;
int32_t tmp_sessions;
int32_t otherwise_relogin_days;
std::unique_ptr<ByteArray> future_auth_token;
std::unique_ptr<User> user;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_auth_exportedAuthorization : public TLObject {
public:
static const uint32_t constructor = 0xb434e2b8;
int64_t id;
std::unique_ptr<ByteArray> bytes;
static TL_auth_exportedAuthorization *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_auth_exportAuthorization : public TLObject {
public:
static const uint32_t constructor = 0xe5bfffcd;
int32_t dc_id;
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_auth_importAuthorization : public TLObject {
public:
static const uint32_t constructor = 0xa57a7dad;
int64_t id;
std::unique_ptr<ByteArray> bytes;
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_updatesTooLong : public TLObject {
public:
static const uint32_t constructor = 0xe317af7e;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionCustomEmoji : public Reaction {
public:
static const uint32_t constructor = 0x8935fc73;
int64_t document_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionEmoji : public Reaction {
public:
static const uint32_t constructor = 0x1b2286b8;
std::string emoticon;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionEmpty : public Reaction {
public:
static const uint32_t constructor = 0x79f5d419;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
#endif

View file

@ -0,0 +1,123 @@
/*
* 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.
*/
#include "BuffersStorage.h"
#include "FileLog.h"
#include "NativeByteBuffer.h"
BuffersStorage &BuffersStorage::getInstance() {
static BuffersStorage instance(true);
return instance;
}
BuffersStorage::BuffersStorage(bool threadSafe) {
isThreadSafe = threadSafe;
if (isThreadSafe) {
pthread_mutex_init(&mutex, NULL);
}
for (uint32_t a = 0; a < 4; a++) {
freeBuffers8.push_back(new NativeByteBuffer((uint32_t) 8));
}
for (uint32_t a = 0; a < 5; a++) {
freeBuffers128.push_back(new NativeByteBuffer((uint32_t) 128));
}
}
NativeByteBuffer *BuffersStorage::getFreeBuffer(uint32_t size) {
uint32_t byteCount = 0;
std::vector<NativeByteBuffer *> *arrayToGetFrom = nullptr;
NativeByteBuffer *buffer = nullptr;
if (size <= 8) {
arrayToGetFrom = &freeBuffers8;
byteCount = 8;
} else if (size <= 128) {
arrayToGetFrom = &freeBuffers128;
byteCount = 128;
} else if (size <= 1024 + 200) {
arrayToGetFrom = &freeBuffers1024;
byteCount = 1024 + 200;
} else if (size <= 4096 + 200) {
arrayToGetFrom = &freeBuffers4096;
byteCount = 4096 + 200;
} else if (size <= 16384 + 200) {
arrayToGetFrom = &freeBuffers16384;
byteCount = 16384 + 200;
} else if (size <= 40000) {
arrayToGetFrom = &freeBuffers32768;
byteCount = 40000;
} else if (size <= 160000) {
arrayToGetFrom = &freeBuffersBig;
byteCount = 160000;
} else {
buffer = new NativeByteBuffer(size);
}
if (arrayToGetFrom != nullptr) {
if (isThreadSafe) {
pthread_mutex_lock(&mutex);
}
if (arrayToGetFrom->size() > 0) {
buffer = (*arrayToGetFrom)[0];
arrayToGetFrom->erase(arrayToGetFrom->begin());
}
if (isThreadSafe) {
pthread_mutex_unlock(&mutex);
}
if (buffer == nullptr) {
buffer = new NativeByteBuffer(byteCount);
if (LOGS_ENABLED) DEBUG_D("create new %u buffer", byteCount);
}
}
if (buffer != nullptr) {
buffer->limit(size);
buffer->rewind();
}
return buffer;
}
void BuffersStorage::reuseFreeBuffer(NativeByteBuffer *buffer) {
if (buffer == nullptr) {
return;
}
std::vector<NativeByteBuffer *> *arrayToReuse = nullptr;
uint32_t capacity = buffer->capacity();
uint32_t maxCount = 10;
if (capacity == 8) {
arrayToReuse = &freeBuffers8;
maxCount = 80;
} else if (capacity == 128) {
arrayToReuse = &freeBuffers128;
maxCount = 80;
} else if (capacity == 1024 + 200) {
arrayToReuse = &freeBuffers1024;
} else if (capacity == 4096 + 200) {
arrayToReuse = &freeBuffers4096;
} else if (capacity == 16384 + 200) {
arrayToReuse = &freeBuffers16384;
} else if (capacity == 40000) {
arrayToReuse = &freeBuffers32768;
} else if (capacity == 160000) {
arrayToReuse = &freeBuffersBig;
}
if (arrayToReuse != nullptr) {
if (isThreadSafe) {
pthread_mutex_lock(&mutex);
}
if (arrayToReuse->size() < maxCount) {
arrayToReuse->push_back(buffer);
} else {
if (LOGS_ENABLED) DEBUG_D("too much %d buffers", capacity);
delete buffer;
}
if (isThreadSafe) {
pthread_mutex_unlock(&mutex);
}
} else {
delete buffer;
}
}

View file

@ -0,0 +1,38 @@
/*
* 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 BUFFERSSTORAGE_H
#define BUFFERSSTORAGE_H
#include <vector>
#include <pthread.h>
#include <stdint.h>
class NativeByteBuffer;
class BuffersStorage {
public:
BuffersStorage(bool threadSafe);
NativeByteBuffer *getFreeBuffer(uint32_t size);
void reuseFreeBuffer(NativeByteBuffer *buffer);
static BuffersStorage &getInstance();
private:
std::vector<NativeByteBuffer *> freeBuffers8;
std::vector<NativeByteBuffer *> freeBuffers128;
std::vector<NativeByteBuffer *> freeBuffers1024;
std::vector<NativeByteBuffer *> freeBuffers4096;
std::vector<NativeByteBuffer *> freeBuffers16384;
std::vector<NativeByteBuffer *> freeBuffers32768;
std::vector<NativeByteBuffer *> freeBuffersBig;
bool isThreadSafe = true;
pthread_mutex_t mutex;
};
#endif

View file

@ -0,0 +1,71 @@
/*
* 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.
*/
#include <stdlib.h>
#include <memory.h>
#include "ByteArray.h"
#include "FileLog.h"
ByteArray::ByteArray() {
bytes = nullptr;
length = 0;
}
ByteArray::ByteArray(uint32_t len) {
bytes = new uint8_t[len];
if (bytes == nullptr) {
if (LOGS_ENABLED) DEBUG_E("unable to allocate byte buffer %u", len);
exit(1);
}
length = len;
}
ByteArray::ByteArray(ByteArray *byteArray) {
bytes = new uint8_t[byteArray->length];
if (bytes == nullptr) {
if (LOGS_ENABLED) DEBUG_E("unable to allocate byte buffer %u", byteArray->length);
exit(1);
}
length = byteArray->length;
memcpy(bytes, byteArray->bytes, length);
}
ByteArray::ByteArray(uint8_t *buffer, uint32_t len) {
bytes = new uint8_t[len];
if (bytes == nullptr) {
if (LOGS_ENABLED) DEBUG_E("unable to allocate byte buffer %u", len);
exit(1);
}
length = len;
memcpy(bytes, buffer, length);
}
ByteArray::~ByteArray() {
if (bytes != nullptr) {
delete[] bytes;
bytes = nullptr;
}
}
void ByteArray::alloc(uint32_t len) {
if (bytes != nullptr) {
delete[] bytes;
bytes = nullptr;
}
bytes = new uint8_t[len];
if (bytes == nullptr) {
if (LOGS_ENABLED) DEBUG_E("unable to allocate byte buffer %u", len);
exit(1);
}
length = len;
}
bool ByteArray::isEqualTo(ByteArray *byteArray) {
return byteArray->length == length && !memcmp(byteArray->bytes, bytes, length);
}

View file

@ -0,0 +1,31 @@
/*
* 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 BYTEARRAY_H
#define BYTEARRAY_H
#include <stdint.h>
class ByteArray {
public:
ByteArray();
ByteArray(uint32_t len);
ByteArray(ByteArray *byteArray);
ByteArray(uint8_t *buffer, uint32_t len);
~ByteArray();
void alloc(uint32_t len);
uint32_t length;
uint8_t *bytes;
bool isEqualTo(ByteArray *byteArray);
};
#endif

View file

@ -0,0 +1,86 @@
/*
* 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.
*/
#include "ByteStream.h"
#include "NativeByteBuffer.h"
ByteStream::ByteStream() {
}
ByteStream::~ByteStream() {
}
void ByteStream::append(NativeByteBuffer *buffer) {
if (buffer == nullptr) {
return;
}
buffersQueue.push_back(buffer);
}
bool ByteStream::hasData() {
size_t size = buffersQueue.size();
for (uint32_t a = 0; a < size; a++) {
if (buffersQueue[a]->hasRemaining()) {
return true;
}
}
return false;
}
void ByteStream::get(NativeByteBuffer *dst) {
if (dst == nullptr) {
return;
}
size_t size = buffersQueue.size();
NativeByteBuffer *buffer;
for (uint32_t a = 0; a < size; a++) {
buffer = buffersQueue[a];
if (buffer->remaining() > dst->remaining()) {
dst->writeBytes(buffer->bytes(), buffer->position(), dst->remaining());
break;
}
dst->writeBytes(buffer->bytes(), buffer->position(), buffer->remaining());
if (!dst->hasRemaining()) {
break;
}
}
}
void ByteStream::discard(uint32_t count) {
uint32_t remaining;
NativeByteBuffer *buffer;
while (count > 0) {
if (buffersQueue.empty()) {
break;
}
buffer = buffersQueue[0];
remaining = buffer->remaining();
if (count < remaining) {
buffer->position(buffer->position() + count);
break;
}
buffer->reuse();
buffersQueue.erase(buffersQueue.begin());
count -= remaining;
}
}
void ByteStream::clean() {
if (buffersQueue.empty()) {
return;
}
size_t size = buffersQueue.size();
for (uint32_t a = 0; a < size; a++) {
NativeByteBuffer *buffer = buffersQueue[a];
buffer->reuse();
}
buffersQueue.clear();
}

View file

@ -0,0 +1,32 @@
/*
* 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 BYTESTREAM_H
#define BYTESTREAM_H
#include <vector>
#include <stdint.h>
class NativeByteBuffer;
class ByteStream {
public:
ByteStream();
~ByteStream();
void append(NativeByteBuffer *buffer);
bool hasData();
void get(NativeByteBuffer *dst);
void discard(uint32_t count);
void clean();
private:
std::vector<NativeByteBuffer *> buffersQueue;
};
#endif

View file

@ -0,0 +1,131 @@
/*
* 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.
*/
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <cstring>
#include "Config.h"
#include "ConnectionsManager.h"
#include "FileLog.h"
#include "BuffersStorage.h"
Config::Config(int32_t instance, std::string fileName) {
instanceNum = instance;
configPath = ConnectionsManager::getInstance(instanceNum).currentConfigPath + fileName;
backupPath = configPath + ".bak";
FILE *backup = fopen(backupPath.c_str(), "rb");
if (backup != nullptr) {
if (LOGS_ENABLED) DEBUG_D("Config(%p, %s) backup file found %s", this, configPath.c_str(), backupPath.c_str());
fclose(backup);
remove(configPath.c_str());
rename(backupPath.c_str(), configPath.c_str());
}
}
NativeByteBuffer *Config::readConfig() {
NativeByteBuffer *buffer = nullptr;
FILE *file = fopen(configPath.c_str(), "rb");
if (file != nullptr) {
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
if (fseek(file, 0, SEEK_SET)) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) failed fseek to begin, reopen it", this, configPath.c_str());
fclose(file);
file = fopen(configPath.c_str(), "rb");
}
uint32_t size = 0;
size_t bytesRead = fread(&size, sizeof(uint32_t), 1, file);
if (LOGS_ENABLED) DEBUG_D("Config(%p, %s) load, size = %u, fileSize = %u", this, configPath.c_str(), size, (uint32_t) fileSize);
if (bytesRead > 0 && size > 0 && (int32_t) size < fileSize) {
buffer = BuffersStorage::getInstance().getFreeBuffer(size);
if (fread(buffer->bytes(), sizeof(uint8_t), size, file) != size) {
buffer->reuse();
buffer = nullptr;
}
}
fclose(file);
}
return buffer;
}
void Config::writeConfig(NativeByteBuffer *buffer) {
if (LOGS_ENABLED) DEBUG_D("Config(%p, %s) start write config", this, configPath.c_str());
FILE *file = fopen(configPath.c_str(), "rb");
FILE *backup = fopen(backupPath.c_str(), "rb");
bool error = false;
bool hasBackupFile = false;
if (file != nullptr) {
if (backup == nullptr) {
fclose(file);
if (rename(configPath.c_str(), backupPath.c_str()) != 0) {
if (LOGS_ENABLED) DEBUG_E("Config(%p) unable to rename file %s to backup file %s", this, configPath.c_str(), backupPath.c_str());
error = true;
} else {
hasBackupFile = true;
}
} else {
fclose(file);
fclose(backup);
remove(configPath.c_str());
}
}
if (error) {
return;
}
file = fopen(configPath.c_str(), "wb");
if (chmod(configPath.c_str(), 0660)) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) chmod failed", this, configPath.c_str());
}
if (file == nullptr) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) unable to open file for writing", this, configPath.c_str());
return;
}
uint32_t size = buffer->position();
if (fwrite(&size, sizeof(uint32_t), 1, file) == 1) {
if (fwrite(buffer->bytes(), sizeof(uint8_t), size, file) != size) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) failed to write config data to file", this, configPath.c_str());
error = true;
}
} else {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) failed to write config size to file", this, configPath.c_str());
error = true;
}
if (fflush(file)) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) fflush failed", this, configPath.c_str());
error = true;
}
int fd = fileno(file);
if (fd == -1) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) fileno failed", this, configPath.c_str());
error = true;
} else {
if (LOGS_ENABLED) DEBUG_D("Config(%p, %s) fileno = %d", this, configPath.c_str(), fd);
}
if (fd != -1 && fsync(fd) == -1) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) fsync failed", this, configPath.c_str());
error = true;
}
if (fclose(file)) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) fclose failed", this, configPath.c_str());
error = true;
}
if (error) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) failed to write config", this, configPath.c_str());
if (remove(configPath.c_str())) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) remove config failed", this, configPath.c_str());
}
} else {
if (hasBackupFile && remove(backupPath.c_str())) {
if (LOGS_ENABLED) DEBUG_E("Config(%p, %s) remove backup failed, %s", this, backupPath.c_str(), strerror(errno));
}
}
if (!error) {
if (LOGS_ENABLED) DEBUG_D("Config(%p, %s) config write ok", this, configPath.c_str());
}
}

View file

@ -0,0 +1,29 @@
/*
* 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 CONFIG_H
#define CONFIG_H
#include <string>
#include "NativeByteBuffer.h"
class Config {
public:
Config(int32_t instance, std::string fileName);
NativeByteBuffer *readConfig();
void writeConfig(NativeByteBuffer *buffer);
private:
int32_t instanceNum;
std::string configPath;
std::string backupPath;
};
#endif

View file

@ -0,0 +1,761 @@
/*
* 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.
*/
#include <openssl/rand.h>
#include <stdlib.h>
#include <cstring>
#include <openssl/sha.h>
#include <algorithm>
#include "Connection.h"
#include "ConnectionsManager.h"
#include "BuffersStorage.h"
#include "FileLog.h"
#include "Timer.h"
#include "Datacenter.h"
#include "NativeByteBuffer.h"
#include "ByteArray.h"
thread_local static uint32_t lastConnectionToken = 1;
Connection::Connection(Datacenter *datacenter, ConnectionType type, int8_t num) : ConnectionSession(datacenter->instanceNum), ConnectionSocket(datacenter->instanceNum) {
currentDatacenter = datacenter;
connectionNum = num;
connectionType = type;
genereateNewSessionId();
connectionState = TcpConnectionStageIdle;
reconnectTimer = new Timer(datacenter->instanceNum, [&] {
reconnectTimer->stop();
waitForReconnectTimer = false;
connect();
});
}
Connection::~Connection() {
if (reconnectTimer != nullptr) {
reconnectTimer->stop();
delete reconnectTimer;
reconnectTimer = nullptr;
}
}
void Connection::suspendConnection() {
suspendConnection(false);
}
void Connection::suspendConnection(bool idle) {
reconnectTimer->stop();
waitForReconnectTimer = false;
if (connectionState == TcpConnectionStageIdle || connectionState == TcpConnectionStageSuspended) {
return;
}
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) suspend", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType);
connectionState = idle ? TcpConnectionStageIdle : TcpConnectionStageSuspended;
dropConnection();
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionClosed(this, 0);
generation++;
firstPacketSent = false;
if (restOfTheData != nullptr) {
restOfTheData->reuse();
restOfTheData = nullptr;
}
lastPacketLength = 0;
connectionToken = 0;
wasConnected = false;
}
void Connection::onReceivedData(NativeByteBuffer *buffer) {
AES_ctr128_encrypt(buffer->bytes(), buffer->bytes(), buffer->limit(), &decryptKey, decryptIv, decryptCount, &decryptNum);
failedConnectionCount = 0;
if (connectionType == ConnectionTypeGeneric || connectionType == ConnectionTypeTemp || connectionType == ConnectionTypeGenericMedia) {
receivedDataAmount += buffer->limit();
if (receivedDataAmount >= 512 * 1024) {
if (currentTimeout > 4) {
currentTimeout -= 2;
setTimeout(currentTimeout);
}
receivedDataAmount = 0;
}
}
NativeByteBuffer *parseLaterBuffer = nullptr;
if (restOfTheData != nullptr) {
if (lastPacketLength == 0) {
if (restOfTheData->capacity() - restOfTheData->position() >= buffer->limit()) {
restOfTheData->limit(restOfTheData->position() + buffer->limit());
restOfTheData->writeBytes(buffer);
buffer = restOfTheData;
} else {
NativeByteBuffer *newBuffer = BuffersStorage::getInstance().getFreeBuffer(restOfTheData->limit() + buffer->limit());
restOfTheData->rewind();
newBuffer->writeBytes(restOfTheData);
newBuffer->writeBytes(buffer);
buffer = newBuffer;
restOfTheData->reuse();
restOfTheData = newBuffer;
}
} else {
uint32_t len;
if (lastPacketLength - restOfTheData->position() <= buffer->limit()) {
len = lastPacketLength - restOfTheData->position();
} else {
len = buffer->limit();
}
uint32_t oldLimit = buffer->limit();
buffer->limit(len);
restOfTheData->writeBytes(buffer);
buffer->limit(oldLimit);
if (restOfTheData->position() == lastPacketLength) {
parseLaterBuffer = buffer->hasRemaining() ? buffer : nullptr;
buffer = restOfTheData;
} else {
// if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received packet size less(%u) then message size(%u)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, restOfTheData->position(), lastPacketLength);
return;
}
}
}
buffer->rewind();
NativeByteBuffer *reuseLater = nullptr;
while (buffer->hasRemaining()) {
if (!hasSomeDataSinceLastConnect) {
currentDatacenter->storeCurrentAddressAndPortNum();
isTryingNextPort = false;
if (connectionType == ConnectionTypeProxy) {
setTimeout(5);
} else if (connectionType == ConnectionTypePush) {
setTimeout(60 * 15);
} else if (connectionType == ConnectionTypeUpload) {
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).networkSlow) {
setTimeout(40);
} else {
setTimeout(25);
}
} else if (connectionType == ConnectionTypeDownload) {
setTimeout(25);
} else {
setTimeout(currentTimeout);
}
}
hasSomeDataSinceLastConnect = true;
uint32_t currentPacketLength = 0;
uint32_t mark = buffer->position();
uint32_t len;
if (currentProtocolType == ProtocolTypeEF) {
uint8_t fByte = buffer->readByte(nullptr);
if ((fByte & (1 << 7)) != 0) {
buffer->position(mark);
if (buffer->remaining() < 4) {
reuseLater = restOfTheData;
restOfTheData = BuffersStorage::getInstance().getFreeBuffer(16384);
restOfTheData->writeBytes(buffer);
restOfTheData->limit(restOfTheData->position());
lastPacketLength = 0;
break;
}
int32_t ackId = buffer->readBigInt32(nullptr) & (~(1 << 31));
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionQuickAckReceived(this, ackId);
continue;
}
if (fByte != 0x7f) {
currentPacketLength = ((uint32_t) fByte) * 4;
} else {
buffer->position(mark);
if (buffer->remaining() < 4) {
if (restOfTheData == nullptr || (restOfTheData != nullptr && restOfTheData->position() != 0)) {
reuseLater = restOfTheData;
restOfTheData = BuffersStorage::getInstance().getFreeBuffer(16384);
restOfTheData->writeBytes(buffer);
restOfTheData->limit(restOfTheData->position());
lastPacketLength = 0;
} else {
restOfTheData->position(restOfTheData->limit());
}
break;
}
currentPacketLength = ((uint32_t) buffer->readInt32(nullptr) >> 8) * 4;
}
len = currentPacketLength + (fByte != 0x7f ? 1 : 4);
} else {
if (buffer->remaining() < 4) {
if (restOfTheData == nullptr || (restOfTheData != nullptr && restOfTheData->position() != 0)) {
reuseLater = restOfTheData;
restOfTheData = BuffersStorage::getInstance().getFreeBuffer(16384);
restOfTheData->writeBytes(buffer);
restOfTheData->limit(restOfTheData->position());
lastPacketLength = 0;
} else {
restOfTheData->position(restOfTheData->limit());
}
break;
}
uint32_t fInt = buffer->readUint32(nullptr);
if ((fInt & (0x80000000)) != 0) {
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionQuickAckReceived(this, fInt & (~(1 << 31)));
continue;
}
currentPacketLength = fInt;
len = currentPacketLength + 4;
}
if (currentProtocolType != ProtocolTypeDD && currentProtocolType != ProtocolTypeTLS && currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received invalid packet length", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType);
reconnect();
break;
}
if (currentPacketLength < buffer->remaining()) {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received message len %u but packet larger %u", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, currentPacketLength, buffer->remaining());
} else if (currentPacketLength == buffer->remaining()) {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received message len %u equal to packet size", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, currentPacketLength);
} else {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received packet size less(%u) then message size(%u)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, buffer->remaining(), currentPacketLength);
if (restOfTheData != nullptr && restOfTheData->capacity() < len) {
reuseLater = restOfTheData;
restOfTheData = nullptr;
}
if (restOfTheData == nullptr) {
buffer->position(mark);
restOfTheData = BuffersStorage::getInstance().getFreeBuffer(len);
restOfTheData->writeBytes(buffer);
} else {
restOfTheData->position(restOfTheData->limit());
restOfTheData->limit(len);
}
lastPacketLength = len;
break;
}
uint32_t old = buffer->limit();
buffer->limit(buffer->position() + currentPacketLength);
uint32_t current_generation = generation;
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionDataReceived(this, buffer, currentPacketLength);
if (current_generation != generation) {
break;
}
buffer->position(buffer->limit());
buffer->limit(old);
if (restOfTheData != nullptr) {
if ((lastPacketLength != 0 && restOfTheData->position() == lastPacketLength) || (lastPacketLength == 0 && !restOfTheData->hasRemaining())) {
reuseLater = restOfTheData;
restOfTheData = nullptr;
} else {
restOfTheData->compact();
restOfTheData->limit(restOfTheData->position());
restOfTheData->position(0);
}
}
if (parseLaterBuffer != nullptr) {
buffer = parseLaterBuffer;
parseLaterBuffer = nullptr;
}
}
if (reuseLater != nullptr) {
reuseLater->reuse();
}
}
void Connection::connect() {
if (waitForReconnectTimer) {
return;
}
if (!ConnectionsManager::getInstance(currentDatacenter->instanceNum).isNetworkAvailable()) {
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionClosed(this, 0);
return;
}
if (connectionState == TcpConnectionStageConnected || connectionState == TcpConnectionStageConnecting) {
return;
}
connectionInProcess = true;
connectionState = TcpConnectionStageConnecting;
isMediaConnection = false;
uint8_t strategy = ConnectionsManager::getInstance(currentDatacenter->instanceNum).getIpStratagy();
uint32_t ipv6;
if (strategy == USE_IPV6_ONLY) {
ipv6 = TcpAddressFlagIpv6;
} else if (strategy == USE_IPV4_IPV6_RANDOM) {
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).lastProtocolUsefullData) {
ipv6 = ConnectionsManager::getInstance(currentDatacenter->instanceNum).lastProtocolIsIpv6 ? TcpAddressFlagIpv6 : 0;
} else {
uint8_t value;
RAND_bytes(&value, 1);
ipv6 = value % 3 == 0 ? TcpAddressFlagIpv6 : 0;
ConnectionsManager::getInstance(currentDatacenter->instanceNum).lastProtocolIsIpv6 = ipv6 != 0;
}
if (connectionType == ConnectionTypeGeneric) {
ConnectionsManager::getInstance(currentDatacenter->instanceNum).lastProtocolUsefullData = false;
}
} else {
ipv6 = 0;
}
uint32_t isStatic = connectionType == ConnectionTypeProxy || !ConnectionsManager::getInstance(currentDatacenter->instanceNum).proxyAddress.empty() ? TcpAddressFlagStatic : 0;
TcpAddress *tcpAddress = nullptr;
if (isMediaConnectionType(connectionType)) {
currentAddressFlags = TcpAddressFlagDownload | isStatic;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags | ipv6);
if (tcpAddress == nullptr) {
currentAddressFlags = isStatic;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags | ipv6);
} else {
isMediaConnection = true;
}
if (tcpAddress == nullptr && ipv6) {
ipv6 = 0;
currentAddressFlags = TcpAddressFlagDownload | isStatic;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags);
if (tcpAddress == nullptr) {
currentAddressFlags = isStatic;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags);
} else {
isMediaConnection = true;
}
}
} else if (connectionType == ConnectionTypeTemp) {
currentAddressFlags = TcpAddressFlagTemp;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags);
ipv6 = 0;
} else {
currentAddressFlags = isStatic;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags | ipv6);
if (tcpAddress == nullptr && ipv6) {
ipv6 = 0;
tcpAddress = currentDatacenter->getCurrentAddress(currentAddressFlags);
}
}
if (tcpAddress == nullptr) {
hostAddress = "";
} else {
hostAddress = tcpAddress->address;
secret = tcpAddress->secret;
}
if (tcpAddress != nullptr && isStatic) {
hostPort = (uint16_t) tcpAddress->port;
} else {
hostPort = (uint16_t) currentDatacenter->getCurrentPort(currentAddressFlags);
}
reconnectTimer->stop();
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) connecting (%s:%hu)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, hostAddress.c_str(), hostPort);
generation++;
firstPacketSent = false;
if (restOfTheData != nullptr) {
restOfTheData->reuse();
restOfTheData = nullptr;
}
lastPacketLength = 0;
wasConnected = false;
hasSomeDataSinceLastConnect = false;
openConnection(hostAddress, hostPort, secret, ipv6 != 0, ConnectionsManager::getInstance(currentDatacenter->instanceNum).currentNetworkType);
if (connectionType == ConnectionTypeProxy) {
setTimeout(5);
} else if (connectionType == ConnectionTypePush) {
if (isTryingNextPort) {
setTimeout(20);
} else {
setTimeout(30);
}
} else if (connectionType == ConnectionTypeUpload) {
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).networkSlow) {
setTimeout(40);
} else {
setTimeout(25);
}
} else {
if (isTryingNextPort) {
setTimeout(8);
} else {
setTimeout(12);
}
}
connectionInProcess = false;
}
void Connection::reconnect() {
if (connectionType == ConnectionTypeProxy) {
suspendConnection(false);
} else {
forceNextPort = true;
suspendConnection(true);
connect();
}
}
bool Connection::hasUsefullData() {
int64_t time = ConnectionsManager::getInstance(currentDatacenter->instanceNum).getCurrentTimeMonotonicMillis();
if (usefullData && llabs(time - usefullDataReceiveTime) < 4 * 1000L) {
return false;
}
return usefullData;
}
bool Connection::isSuspended() {
return connectionState == TcpConnectionStageSuspended;
}
bool Connection::isMediaConnectionType(ConnectionType type) {
return (type & ConnectionTypeGenericMedia) != 0 || (type & ConnectionTypeDownload) != 0;
}
void Connection::setHasUsefullData() {
if (!usefullData) {
usefullDataReceiveTime = ConnectionsManager::getInstance(currentDatacenter->instanceNum).getCurrentTimeMonotonicMillis();
usefullData = true;
lastReconnectTimeout = 50;
}
}
bool Connection::allowsCustomPadding() {
return currentProtocolType == ProtocolTypeTLS || currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeEF;
}
void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted) {
if (buff == nullptr) {
return;
}
buff->rewind();
if (connectionState == TcpConnectionStageIdle || connectionState == TcpConnectionStageReconnecting || connectionState == TcpConnectionStageSuspended) {
connect();
}
if (isDisconnected()) {
buff->reuse();
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) disconnected, don't send data", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType);
return;
}
uint32_t bufferLen = 0;
uint32_t packetLength;
uint8_t useSecret = 0;
if (!firstPacketSent) {
if (!overrideProxyAddress.empty()) {
if (!overrideProxySecret.empty()) {
useSecret = 1;
} else if (!secret.empty()) {
useSecret = 2;
}
} else if (!ConnectionsManager::getInstance(currentDatacenter->instanceNum).proxyAddress.empty() && !ConnectionsManager::getInstance(currentDatacenter->instanceNum).proxySecret.empty()) {
useSecret = 1;
} else if (!secret.empty()) {
useSecret = 2;
}
if (useSecret != 0) {
std::string *currentSecret = getCurrentSecret(useSecret);
if (currentSecret->length() >= 17 && (*currentSecret)[0] == '\xdd') {
currentProtocolType = ProtocolTypeDD;
} else if (currentSecret->length() > 17 && (*currentSecret)[0] == '\xee') {
currentProtocolType = ProtocolTypeTLS;
} else {
currentProtocolType = ProtocolTypeEF;
}
} else {
currentProtocolType = ProtocolTypeEF;
}
}
uint32_t additinalPacketSize = 0;
if (currentProtocolType == ProtocolTypeEF) {
packetLength = buff->limit() / 4;
if (packetLength < 0x7f) {
bufferLen++;
} else {
bufferLen += 4;
}
} else {
packetLength = buff->limit();
if (currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeTLS) {
RAND_bytes((uint8_t *) &additinalPacketSize, 4);
if (!encrypted) {
additinalPacketSize = additinalPacketSize % 257;
} else {
additinalPacketSize = additinalPacketSize % 16;
}
packetLength += additinalPacketSize;
} else {
RAND_bytes((uint8_t *) &additinalPacketSize, 4);
if (!encrypted) {
additinalPacketSize = additinalPacketSize % 257;
uint32_t additionalSize = additinalPacketSize % 4;
if (additionalSize != 0) {
additinalPacketSize += (4 - additionalSize);
}
}
packetLength += additinalPacketSize;
}
bufferLen += 4;
}
if (!firstPacketSent) {
bufferLen += 64;
}
NativeByteBuffer *buffer = BuffersStorage::getInstance().getFreeBuffer(bufferLen);
NativeByteBuffer *buffer2;
if (additinalPacketSize > 0) {
buffer2 = BuffersStorage::getInstance().getFreeBuffer(additinalPacketSize);
RAND_bytes(buffer2->bytes(), additinalPacketSize);
} else {
buffer2 = nullptr;
}
uint8_t *bytes = buffer->bytes();
if (!firstPacketSent) {
buffer->position(64);
while (true) {
RAND_bytes(bytes, 64);
uint32_t val = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0]);
uint32_t val2 = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | (bytes[4]);
if (currentProtocolType == ProtocolTypeTLS || bytes[0] != 0xef && val != 0x44414548 && val != 0x54534f50 && val != 0x20544547 && val != 0x4954504f && val != 0xeeeeeeee && val != 0xdddddddd && val != 0x02010316 && val2 != 0x00000000) {
if (currentProtocolType == ProtocolTypeEF) {
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xef;
} else if (currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeTLS) {
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xdd;
} else if (currentProtocolType == ProtocolTypeEE) {
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xee;
}
if (useSecret != 0) {
int16_t datacenterId;
if (isMediaConnection) {
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).testBackend) {
datacenterId = -(int16_t) (10000 + currentDatacenter->getDatacenterId());
} else {
datacenterId = -(int16_t) currentDatacenter->getDatacenterId();
}
} else {
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).testBackend) {
datacenterId = (int16_t) (10000 + currentDatacenter->getDatacenterId());
} else {
datacenterId = (int16_t) currentDatacenter->getDatacenterId();
}
}
bytes[60] = (uint8_t) (datacenterId & 0xff);
bytes[61] = (uint8_t) ((datacenterId >> 8) & 0xff);
}
break;
}
}
encryptNum = decryptNum = 0;
memset(encryptCount, 0, 16);
memset(decryptCount, 0, 16);
for (int32_t a = 0; a < 48; a++) {
temp[a] = bytes[a + 8];
}
encryptKeyWithSecret(temp, useSecret);
if (AES_set_encrypt_key(temp, 256, &encryptKey) < 0) {
if (LOGS_ENABLED) DEBUG_E("unable to set encryptKey");
exit(1);
}
memcpy(encryptIv, temp + 32, 16);
for (int32_t a = 0; a < 48; a++) {
temp[a] = bytes[55 - a];
}
encryptKeyWithSecret(temp, useSecret);
if (AES_set_encrypt_key(temp, 256, &decryptKey) < 0) {
if (LOGS_ENABLED) DEBUG_E("unable to set decryptKey");
exit(1);
}
memcpy(decryptIv, temp + 32, 16);
AES_ctr128_encrypt(bytes, temp, 64, &encryptKey, encryptIv, encryptCount, &encryptNum);
memcpy(bytes + 56, temp + 56, 8);
firstPacketSent = true;
}
if (currentProtocolType == ProtocolTypeEF) {
if (packetLength < 0x7f) {
if (reportAck) {
packetLength |= (1 << 7);
}
buffer->writeByte((uint8_t) packetLength);
bytes += (buffer->limit() - 1);
AES_ctr128_encrypt(bytes, bytes, 1, &encryptKey, encryptIv, encryptCount, &encryptNum);
} else {
packetLength = (packetLength << 8) + 0x7f;
if (reportAck) {
packetLength |= (1 << 7);
}
buffer->writeInt32(packetLength);
bytes += (buffer->limit() - 4);
AES_ctr128_encrypt(bytes, bytes, 4, &encryptKey, encryptIv, encryptCount, &encryptNum);
}
} else {
if (reportAck) {
packetLength |= 0x80000000;
}
buffer->writeInt32(packetLength);
bytes += (buffer->limit() - 4);
AES_ctr128_encrypt(bytes, bytes, 4, &encryptKey, encryptIv, encryptCount, &encryptNum);
}
buffer->rewind();
writeBuffer(buffer);
buff->rewind();
AES_ctr128_encrypt(buff->bytes(), buff->bytes(), buff->limit(), &encryptKey, encryptIv, encryptCount, &encryptNum);
writeBuffer(buff);
if (buffer2 != nullptr) {
AES_ctr128_encrypt(buffer2->bytes(), buffer2->bytes(), buffer2->limit(), &encryptKey, encryptIv, encryptCount, &encryptNum);
writeBuffer(buffer2);
}
}
inline std::string *Connection::getCurrentSecret(uint8_t secretType) {
if (secretType == 2) {
return &secret;
} else if (!overrideProxySecret.empty()) {
return &overrideProxySecret;
} else {
return &ConnectionsManager::getInstance(currentDatacenter->instanceNum).proxySecret;
}
}
inline void Connection::encryptKeyWithSecret(uint8_t *bytes, uint8_t secretType) {
if (secretType == 0) {
return;
}
std::string *currentSecret = getCurrentSecret(secretType);
size_t a = 0;
size_t size = std::min((size_t) 16, currentSecret->length());
if (currentSecret->length() >= 17 && ((*currentSecret)[0] == '\xdd' || (*currentSecret)[0] == '\xee')) {
a = 1;
size = 17;
}
SHA256_CTX sha256Ctx;
SHA256_Init(&sha256Ctx);
SHA256_Update(&sha256Ctx, bytes, 32);
char b[1];
for (; a < size; a++) {
b[0] = (char) (*currentSecret)[a];
SHA256_Update(&sha256Ctx, b, 1);
}
SHA256_Final(bytes, &sha256Ctx);
}
void Connection::onDisconnectedInternal(int32_t reason, int32_t error) {
reconnectTimer->stop();
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) disconnected with reason %d", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, reason);
bool switchToNextPort = reason == 2 && wasConnected && (!hasSomeDataSinceLastConnect || currentDatacenter->isCustomPort(currentAddressFlags)) || forceNextPort;
if (connectionType == ConnectionTypeGeneric || connectionType == ConnectionTypeTemp || connectionType == ConnectionTypeGenericMedia) {
if (wasConnected && reason == 2 && currentTimeout < 16) {
currentTimeout += 2;
}
}
generation++;
firstPacketSent = false;
if (restOfTheData != nullptr) {
restOfTheData->reuse();
restOfTheData = nullptr;
}
lastPacketLength = 0;
receivedDataAmount = 0;
wasConnected = false;
if (connectionState != TcpConnectionStageSuspended && connectionState != TcpConnectionStageIdle) {
connectionState = TcpConnectionStageIdle;
}
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionClosed(this, reason);
connectionToken = 0;
uint32_t datacenterId = currentDatacenter->getDatacenterId();
if (connectionState == TcpConnectionStageIdle) {
connectionState = TcpConnectionStageReconnecting;
failedConnectionCount++;
if (failedConnectionCount == 1) {
if (hasUsefullData()) {
willRetryConnectCount = 3;
} else {
willRetryConnectCount = 1;
}
}
if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).isNetworkAvailable() && connectionType != ConnectionTypeProxy) {
isTryingNextPort = true;
if (failedConnectionCount > willRetryConnectCount || switchToNextPort) {
currentDatacenter->nextAddressOrPort(currentAddressFlags);
if (currentDatacenter->isRepeatCheckingAddresses() && (ConnectionsManager::getInstance(currentDatacenter->instanceNum).getIpStratagy() == USE_IPV4_ONLY || ConnectionsManager::getInstance(currentDatacenter->instanceNum).getIpStratagy() == USE_IPV6_ONLY)) {
if (LOGS_ENABLED) DEBUG_D("started retrying connection, set ipv4 ipv6 random strategy");
ConnectionsManager::getInstance(currentDatacenter->instanceNum).setIpStrategy(USE_IPV4_IPV6_RANDOM);
}
failedConnectionCount = 0;
}
}
if (error == 0x68 || error == 0x71) {
if (connectionType != ConnectionTypeProxy) {
waitForReconnectTimer = true;
reconnectTimer->setTimeout(lastReconnectTimeout, false);
lastReconnectTimeout *= 2;
if (lastReconnectTimeout > 400) {
lastReconnectTimeout = 400;
}
reconnectTimer->start();
}
} else {
waitForReconnectTimer = false;
if (connectionType == ConnectionTypeGenericMedia && currentDatacenter->isHandshaking(true) || connectionType == ConnectionTypeGeneric && (currentDatacenter->isHandshaking(false) || datacenterId == ConnectionsManager::getInstance(currentDatacenter->instanceNum).currentDatacenterId || datacenterId == ConnectionsManager::getInstance(currentDatacenter->instanceNum).movingToDatacenterId)) {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) reconnect %s:%hu", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, hostAddress.c_str(), hostPort);
reconnectTimer->setTimeout(1000, false);
reconnectTimer->start();
}
}
}
usefullData = false;
}
void Connection::onDisconnected(int32_t reason, int32_t error) {
if (connectionInProcess) {
ConnectionsManager::getInstance(currentDatacenter->instanceNum).scheduleTask([&, reason, error] {
onDisconnectedInternal(reason, error);
});
} else {
onDisconnectedInternal(reason, error);
}
}
void Connection::onConnected() {
connectionState = TcpConnectionStageConnected;
connectionToken = lastConnectionToken++;
wasConnected = true;
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) connected to %s:%hu", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, hostAddress.c_str(), hostPort);
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionConnected(this);
}
bool Connection::hasPendingRequests() {
return ConnectionsManager::getInstance(currentDatacenter->instanceNum).hasPendingRequestsForConnection(this);
}
Datacenter *Connection::getDatacenter() {
return currentDatacenter;
}
ConnectionType Connection::getConnectionType() {
return connectionType;
}
int8_t Connection::getConnectionNum() {
return connectionNum;
}
uint32_t Connection::getConnectionToken() {
return connectionToken;
}

View file

@ -0,0 +1,121 @@
/*
* 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 CONNECTION_H
#define CONNECTION_H
#include <pthread.h>
#include <vector>
#include <string>
#include <openssl/aes.h>
#include "ConnectionSession.h"
#include "ConnectionSocket.h"
#include "Defines.h"
class Datacenter;
class Timer;
class ByteStream;
class ByteArray;
class Connection : public ConnectionSession, public ConnectionSocket {
public:
Connection(Datacenter *datacenter, ConnectionType type, int8_t num);
~Connection();
void connect();
void suspendConnection();
void suspendConnection(bool idle);
void sendData(NativeByteBuffer *buffer, bool reportAck, bool encrypted);
bool hasUsefullData();
void setHasUsefullData();
bool allowsCustomPadding();
uint32_t getConnectionToken();
ConnectionType getConnectionType();
int8_t getConnectionNum();
Datacenter *getDatacenter();
bool isSuspended();
static bool isMediaConnectionType(ConnectionType type);
protected:
void onReceivedData(NativeByteBuffer *buffer) override;
void onDisconnected(int32_t reason, int32_t error) override;
void onConnected() override;
bool hasPendingRequests() override;
void reconnect();
private:
enum TcpConnectionState {
TcpConnectionStageIdle,
TcpConnectionStageConnecting,
TcpConnectionStageReconnecting,
TcpConnectionStageConnected,
TcpConnectionStageSuspended
};
enum ProtocolType {
ProtocolTypeEF,
ProtocolTypeEE,
ProtocolTypeDD,
ProtocolTypeTLS
};
inline void encryptKeyWithSecret(uint8_t *array, uint8_t secretType);
inline std::string *getCurrentSecret(uint8_t secretType);
void onDisconnectedInternal(int32_t reason, int32_t error);
ProtocolType currentProtocolType = ProtocolTypeEE;
TcpConnectionState connectionState = TcpConnectionStageIdle;
uint32_t connectionToken = 0;
std::string hostAddress;
std::string secret;
uint16_t hostPort;
uint16_t failedConnectionCount;
Datacenter *currentDatacenter;
uint32_t currentAddressFlags;
ConnectionType connectionType;
int8_t connectionNum;
bool firstPacketSent = false;
NativeByteBuffer *restOfTheData = nullptr;
uint32_t lastPacketLength = 0;
bool hasSomeDataSinceLastConnect = false;
bool isTryingNextPort = false;
bool wasConnected = false;
uint32_t willRetryConnectCount = 5;
Timer *reconnectTimer;
bool usefullData = false;
bool forceNextPort = false;
bool isMediaConnection = false;
bool waitForReconnectTimer = false;
bool connectionInProcess = false;
uint32_t lastReconnectTimeout = 100;
int64_t usefullDataReceiveTime;
uint32_t currentTimeout = 4;
uint32_t receivedDataAmount = 0;
uint32_t generation = 0;
uint8_t temp[64];
AES_KEY encryptKey;
uint8_t encryptIv[16];
uint32_t encryptNum;
uint8_t encryptCount[16];
AES_KEY decryptKey;
uint8_t decryptIv[16];
uint32_t decryptNum;
uint8_t decryptCount[16];
friend class ConnectionsManager;
};
#endif

View file

@ -0,0 +1,114 @@
/*
* 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.
*/
#include <algorithm>
#include <openssl/rand.h>
#include "ConnectionSession.h"
#include "MTProtoScheme.h"
#include "ConnectionsManager.h"
#include "NativeByteBuffer.h"
ConnectionSession::ConnectionSession(int32_t instance) {
instanceNum = instance;
}
void ConnectionSession::recreateSession() {
processedMessageIds.clear();
messagesIdsForConfirmation.clear();
processedSessionChanges.clear();
nextSeqNo = 0;
genereateNewSessionId();
}
void ConnectionSession::genereateNewSessionId() {
int64_t newSessionId;
RAND_bytes((uint8_t *) &newSessionId, 8);
#if USE_DEBUG_SESSION
sessionId = (0xabcd000000000000L | (newSessionId & 0x0000ffffffffffffL));
#else
sessionId = newSessionId;
#endif
}
void ConnectionSession::setSessionId(int64_t id) {
sessionId = id;
}
int64_t ConnectionSession::getSessionId() {
return sessionId;
}
uint32_t ConnectionSession::generateMessageSeqNo(bool increment) {
uint32_t value = nextSeqNo;
if (increment) {
nextSeqNo++;
}
return value * 2 + (increment ? 1 : 0);
}
int32_t ConnectionSession::isMessageIdProcessed(int64_t messageId) {
if (!(messageId & 1)) {
return 1;
}
if (minProcessedMessageId != 0 && messageId < minProcessedMessageId) {
return 2;
}
if (std::find(processedMessageIds.begin(), processedMessageIds.end(), messageId) != processedMessageIds.end()) {
return 1;
}
return 0;
}
void ConnectionSession::addProcessedMessageId(int64_t messageId) {
if (processedMessageIds.size() > 300) {
std::sort(processedMessageIds.begin(), processedMessageIds.end());
processedMessageIds.erase(processedMessageIds.begin(), processedMessageIds.begin() + 100);
minProcessedMessageId = *(processedMessageIds.begin());
}
processedMessageIds.push_back(messageId);
}
bool ConnectionSession::hasMessagesToConfirm() {
return !messagesIdsForConfirmation.empty();
}
void ConnectionSession::addMessageToConfirm(int64_t messageId) {
if (std::find(messagesIdsForConfirmation.begin(), messagesIdsForConfirmation.end(), messageId) != messagesIdsForConfirmation.end()) {
return;
}
messagesIdsForConfirmation.push_back(messageId);
}
NetworkMessage *ConnectionSession::generateConfirmationRequest() {
NetworkMessage *networkMessage = nullptr;
if (!messagesIdsForConfirmation.empty()) {
TL_msgs_ack *msgAck = new TL_msgs_ack();
msgAck->msg_ids.insert(msgAck->msg_ids.begin(), messagesIdsForConfirmation.begin(), messagesIdsForConfirmation.end());
NativeByteBuffer *os = new NativeByteBuffer(true);
msgAck->serializeToStream(os);
networkMessage = new NetworkMessage();
networkMessage->message = std::unique_ptr<TL_message>(new TL_message);
networkMessage->message->msg_id = ConnectionsManager::getInstance(instanceNum).generateMessageId();
networkMessage->message->seqno = generateMessageSeqNo(false);
networkMessage->message->bytes = os->capacity();
networkMessage->message->body = std::unique_ptr<TLObject>(msgAck);
messagesIdsForConfirmation.clear();
}
return networkMessage;
}
bool ConnectionSession::isSessionProcessed(int64_t sessionId) {
return std::find(processedSessionChanges.begin(), processedSessionChanges.end(), sessionId) != processedSessionChanges.end();
}
void ConnectionSession::addProcessedSession(int64_t sessionId) {
processedSessionChanges.push_back(sessionId);
}

View file

@ -0,0 +1,45 @@
/*
* 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 CONNECTIONSESSION_H
#define CONNECTIONSESSION_H
#include <stdint.h>
#include <vector>
#include "Defines.h"
class ConnectionSession {
public:
ConnectionSession(int32_t instance);
void recreateSession();
void genereateNewSessionId();
void setSessionId(int64_t id);
int64_t getSessionId();
uint32_t generateMessageSeqNo(bool increment);
int32_t isMessageIdProcessed(int64_t messageId);
void addProcessedMessageId(int64_t messageId);
bool hasMessagesToConfirm();
void addMessageToConfirm(int64_t messageId);
NetworkMessage *generateConfirmationRequest();
bool isSessionProcessed(int64_t sessionId);
void addProcessedSession(int64_t sessionId);
private:
int32_t instanceNum;
int64_t sessionId;
uint32_t nextSeqNo = 0;
int64_t minProcessedMessageId = 0;
std::vector<int64_t> processedMessageIds;
std::vector<int64_t> messagesIdsForConfirmation;
std::vector<int64_t> processedSessionChanges;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
/*
* 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 CONNECTIONSOCKET_H
#define CONNECTIONSOCKET_H
#include <sys/epoll.h>
#include <netinet/in.h>
#include <string>
class NativeByteBuffer;
class ConnectionsManager;
class ByteStream;
class EventObject;
class ByteArray;
class ConnectionSocket {
public:
ConnectionSocket(int32_t instance);
virtual ~ConnectionSocket();
void writeBuffer(uint8_t *data, uint32_t size);
void writeBuffer(NativeByteBuffer *buffer);
void openConnection(std::string address, uint16_t port, std::string secret, bool ipv6, int32_t networkType);
void setTimeout(time_t timeout);
time_t getTimeout();
bool isDisconnected();
void dropConnection();
void setOverrideProxy(std::string address, uint16_t port, std::string username, std::string password, std::string secret);
void onHostNameResolved(std::string host, std::string ip, bool ipv6);
protected:
int32_t instanceNum;
void onEvent(uint32_t events);
bool checkTimeout(int64_t now);
void resetLastEventTime();
bool hasTlsHashMismatch();
virtual void onReceivedData(NativeByteBuffer *buffer) = 0;
virtual void onDisconnected(int32_t reason, int32_t error) = 0;
virtual void onConnected() = 0;
virtual bool hasPendingRequests() = 0;
std::string overrideProxyUser = "";
std::string overrideProxyPassword = "";
std::string overrideProxyAddress = "";
std::string overrideProxySecret = "";
uint16_t overrideProxyPort = 1080;
private:
ByteStream *outgoingByteStream = nullptr;
struct epoll_event eventMask;
struct sockaddr_in socketAddress;
struct sockaddr_in6 socketAddress6;
int socketFd = -1;
time_t timeout = 12;
bool onConnectedSent = false;
int64_t lastEventTime = 0;
EventObject *eventObject;
int32_t currentNetworkType;
bool isIpv6;
std::string currentAddress;
uint16_t currentPort;
std::string waitingForHostResolve;
bool adjustWriteOpAfterResolve;
std::string currentSecret;
std::string currentSecretDomain;
bool tlsUseLegacy = false;
bool tlsHashMismatch = false;
bool tlsBufferSized = true;
NativeByteBuffer *tlsBuffer = nullptr;
ByteArray *tempBuffer = nullptr;
size_t bytesRead = 0;
int8_t tlsState = 0;
uint8_t proxyAuthState;
int32_t checkSocketError(int32_t *error);
void closeSocket(int32_t reason, int32_t error);
void openConnectionInternal(bool ipv6);
void adjustWriteOp();
friend class EventObject;
friend class ConnectionsManager;
friend class Connection;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,277 @@
/*
* 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 <sys/epoll.h>
#include <map>
#include <atomic>
#include <unordered_set>
#include "Defines.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;
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();
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);
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 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, onRequestTimeFunc requestTimeFunc, jobject ptr1);
#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);
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);
void sendMessagesToConnection(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck);
void sendMessagesToConnectionWithConfirmation(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck);
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 moveToDatacenter(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);
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);
int32_t instanceNum = 0;
uint32_t configVersion = 5;
Config *config = nullptr;
std::list<EventObject *> events;
std::map<uint32_t, Datacenter *> datacenters;
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;
bool registeringForPush = false;
int64_t lastPushPingTime = 0;
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;
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;
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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,154 @@
/*
* 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 DATACENTER_H
#define DATACENTER_H
#include <stdint.h>
#include <vector>
#include <map>
#include "Defines.h"
class TL_future_salt;
class Connection;
class NativeByteBuffer;
class TL_future_salt;
class TL_future_salts;
class TL_help_configSimple;
class ByteArray;
class TLObject;
class Config;
class Handshake;
class Datacenter : public HandshakeDelegate {
public:
Datacenter(int32_t instance, uint32_t id);
Datacenter(int32_t instance, NativeByteBuffer *data);
uint32_t getDatacenterId();
TcpAddress *getCurrentAddress(uint32_t flags);
int32_t getCurrentPort(uint32_t flags);
void addAddressAndPort(std::string address, uint32_t port, uint32_t flags, std::string secret);
void nextAddressOrPort(uint32_t flags);
bool isCustomPort(uint32_t flags);
void storeCurrentAddressAndPortNum();
void replaceAddresses(std::vector<TcpAddress> &newAddresses, uint32_t flags);
void serializeToStream(NativeByteBuffer *stream);
void clearAuthKey(HandshakeType type);
void clearServerSalts(bool media);
int64_t getServerSalt(bool media);
void mergeServerSalts(TL_future_salts *newSalts, bool media);
void addServerSalt(std::unique_ptr<TL_future_salt> &serverSalt, bool media);
bool containsServerSalt(int64_t value, bool media);
void suspendConnections(bool suspendPush);
void getSessions(std::vector<int64_t> &sessions);
void recreateSessions(HandshakeType type);
void resetAddressAndPortNum();
bool isHandshakingAny();
bool isHandshaking(bool media);
bool isHandshaking(HandshakeType type);
bool hasAuthKey(ConnectionType connectionTyoe, int32_t allowPendingKey);
bool hasPermanentAuthKey();
int64_t getPermanentAuthKeyId();
bool isExportingAuthorization();
bool hasMediaAddress();
void resetInitVersion();
bool isRepeatCheckingAddresses();
Connection *getDownloadConnection(uint8_t num, bool create);
Connection *getProxyConnection(uint8_t num, bool create, bool connect);
Connection *getUploadConnection(uint8_t num, bool create);
Connection *getGenericConnection(bool create, int32_t allowPendingKey);
Connection *getGenericMediaConnection(bool create, int32_t allowPendingKey);
Connection *getPushConnection(bool create);
Connection *getTempConnection(bool create);
Connection *getConnectionByType(uint32_t connectionType, bool create, int32_t allowPendingKey);
static void aesIgeEncryption(uint8_t *buffer, uint8_t *key, uint8_t *iv, bool encrypt, bool changeIv, uint32_t length);
private:
void onHandshakeConnectionClosed(Connection *connection);
void onHandshakeConnectionConnected(Connection *connection);
void onHandshakeComplete(Handshake *handshake, int64_t keyId, ByteArray *authKey, int32_t timeDifference);
void processHandshakeResponse(bool media, TLObject *message, int64_t messageId);
NativeByteBuffer *createRequestsData(std::vector<std::unique_ptr<NetworkMessage>> &requests, int32_t *quickAckId, Connection *connection, bool pfsInit);
bool decryptServerResponse(int64_t keyId, uint8_t *key, uint8_t *data, uint32_t length, Connection *connection);
TLObject *getCurrentHandshakeRequest(bool media);
ByteArray *getAuthKey(ConnectionType connectionType, bool perm, int64_t *authKeyId, int32_t allowPendingKey);
const int32_t *defaultPorts = new int32_t[4] {-1, 443, 5222, -1};
int32_t instanceNum;
uint32_t datacenterId;
Connection *genericConnection = nullptr;
Connection *genericMediaConnection = nullptr;
Connection *tempConnection = nullptr;
Connection *proxyConnection[PROXY_CONNECTIONS_COUNT];
Connection *downloadConnection[DOWNLOAD_CONNECTIONS_COUNT];
Connection *uploadConnection[UPLOAD_CONNECTIONS_COUNT];
Connection *pushConnection = nullptr;
uint32_t lastInitVersion = 0;
uint32_t lastInitMediaVersion = 0;
bool authorized = false;
std::vector<TcpAddress> addressesIpv4;
std::vector<TcpAddress> addressesIpv6;
std::vector<TcpAddress> addressesIpv4Download;
std::vector<TcpAddress> addressesIpv6Download;
std::vector<TcpAddress> addressesIpv4Temp;
std::vector<std::unique_ptr<TL_future_salt>> serverSalts;
std::vector<std::unique_ptr<TL_future_salt>> mediaServerSalts;
uint32_t currentPortNumIpv4 = 0;
uint32_t currentAddressNumIpv4 = 0;
uint32_t currentPortNumIpv4Temp = 0;
uint32_t currentAddressNumIpv4Temp = 0;
uint32_t currentPortNumIpv6 = 0;
uint32_t currentAddressNumIpv6 = 0;
uint32_t currentPortNumIpv4Download = 0;
uint32_t currentAddressNumIpv4Download = 0;
uint32_t currentPortNumIpv6Download = 0;
uint32_t currentAddressNumIpv6Download = 0;
ByteArray *authKeyPerm = nullptr;
int64_t authKeyPermId = 0;
ByteArray *authKeyTemp = nullptr;
int64_t authKeyTempId = 0;
ByteArray *authKeyMediaTemp = nullptr;
int64_t authKeyMediaTempId = 0;
Config *config = nullptr;
bool isCdnDatacenter = false;
bool repeatCheckingAddresses = false;
std::vector<std::unique_ptr<Handshake>> handshakes;
const uint32_t configVersion = 13;
const uint32_t paramsConfigVersion = 1;
Connection *createProxyConnection(uint8_t num);
Connection *createDownloadConnection(uint8_t num);
Connection *createUploadConnection(uint8_t num);
Connection *createGenericConnection();
Connection *createGenericMediaConnection();
Connection *createTempConnection();
Connection *createPushConnection();
Connection *createConnectionByType(uint32_t connectionType);
void beginHandshake(HandshakeType handshakeType, bool reconnect);
bool exportingAuthorization = false;
void exportAuthorization();
static TL_help_configSimple *decodeSimpleConfig(NativeByteBuffer *buffer);
friend class ConnectionsManager;
friend class Connection;
friend class Handshake;
friend class Request;
};
#endif

View file

@ -0,0 +1,207 @@
/*
* 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 DEFINES_H
#define DEFINES_H
#include <functional>
#include <list>
#include <limits.h>
#include <sstream>
#include <inttypes.h>
#include "ByteArray.h"
#define USE_DEBUG_SESSION false
#define READ_BUFFER_SIZE 1024 * 1024 * 2
//#define DEBUG_VERSION
#define PFS_ENABLED 1
#define DEFAULT_DATACENTER_ID INT_MAX
#define DC_UPDATE_TIME 60 * 60
#define TEMP_AUTH_KEY_EXPIRE_TIME 24 * 60 * 60
#define PROXY_CONNECTIONS_COUNT 4
#define DOWNLOAD_CONNECTIONS_COUNT 2
#define UPLOAD_CONNECTIONS_COUNT 4
#define CONNECTION_BACKGROUND_KEEP_TIME 10000
#define MAX_ACCOUNT_COUNT 5
#define USE_DELEGATE_HOST_RESOLVE
#define USE_IPV4_ONLY 0
#define USE_IPV6_ONLY 1
#define USE_IPV4_IPV6_RANDOM 2
#define NETWORK_TYPE_MOBILE 0
#define NETWORK_TYPE_WIFI 1
#define NETWORK_TYPE_ROAMING 2
class TLObject;
class TL_error;
class Request;
class TL_message;
class TL_config;
class NativeByteBuffer;
class Handshake;
class ConnectionSocket;
typedef std::function<void(TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId, int32_t dcId)> onCompleteFunc;
typedef std::function<void()> onQuickAckFunc;
typedef std::function<void()> onWriteToSocketFunc;
typedef std::function<void()> onRequestClearFunc;
typedef std::function<void()> onRequestCancelDoneFunc;
typedef std::function<void(int64_t messageId)> fillParamsFunc;
typedef std::function<void(int64_t requestTime)> onRequestTimeFunc;
typedef std::list<std::unique_ptr<Request>> requestsList;
typedef requestsList::iterator requestsIter;
typedef struct NetworkMessage {
std::unique_ptr<TL_message> message;
bool invokeAfter = false;
bool needQuickAck = false;
bool forceContainer = false;
int32_t requestId;
} NetworkMessage;
enum ConnectionType {
ConnectionTypeGeneric = 1,
ConnectionTypeDownload = 2,
ConnectionTypeUpload = 4,
ConnectionTypePush = 8,
ConnectionTypeTemp = 16,
ConnectionTypeProxy = 32,
ConnectionTypeGenericMedia = 64
};
enum TcpAddressFlag {
TcpAddressFlagIpv6 = 1,
TcpAddressFlagDownload = 2,
TcpAddressFlagO = 4,
TcpAddressFlagCdn = 8,
TcpAddressFlagStatic = 16,
TcpAddressFlagTemp = 2048
};
enum ConnectionState {
ConnectionStateConnecting = 1,
ConnectionStateWaitingForNetwork = 2,
ConnectionStateConnected = 3,
ConnectionStateConnectingViaProxy = 4
};
enum EventObjectType {
EventObjectTypeConnection,
EventObjectTypeTimer,
EventObjectTypePipe,
EventObjectTypeEvent
};
enum FileLoadState {
FileLoadStateIdle,
FileLoadStateDownloading,
FileLoadStateFailed,
FileLoadStateFinished
};
enum FileLoadFailReason {
FileLoadFailReasonError,
FileLoadFailReasonCanceled,
FileLoadFailReasonRetryLimit
};
enum HandshakeType {
HandshakeTypePerm,
HandshakeTypeTemp,
HandshakeTypeMediaTemp,
HandshakeTypeCurrent,
HandshakeTypeAll
};
class TcpAddress {
public:
std::string address;
int32_t flags;
int32_t port;
std::string secret;
TcpAddress(std::string addr, int32_t p, int32_t f, std::string s) {
address = addr;
port = p;
flags = f;
secret = s;
}
};
typedef std::function<void(std::string path)> onFinishedFunc;
typedef std::function<void(FileLoadFailReason reason)> onFailedFunc;
typedef std::function<void(float progress)> onProgressChangedFunc;
typedef struct ConnectiosManagerDelegate {
virtual void onUpdate(int32_t instanceNum) = 0;
virtual void onSessionCreated(int32_t instanceNum) = 0;
virtual void onConnectionStateChanged(ConnectionState state, int32_t instanceNum) = 0;
virtual void onUnparsedMessageReceived(int64_t reqMessageId, NativeByteBuffer *buffer, ConnectionType connectionType, int32_t instanceNum) = 0;
virtual void onLogout(int32_t instanceNum) = 0;
virtual void onUpdateConfig(TL_config *config, int32_t instanceNum) = 0;
virtual void onInternalPushReceived(int32_t instanceNum) = 0;
virtual void onBytesSent(int32_t amount, int32_t networkType, int32_t instanceNum) = 0;
virtual void onBytesReceived(int32_t amount, int32_t networkType, int32_t instanceNum) = 0;
virtual void onRequestNewServerIpAndPort(int32_t second, int32_t instanceNum) = 0;
virtual void onProxyError(int32_t instanceNum) = 0;
virtual void getHostByName(std::string domain, int32_t instanceNum, ConnectionSocket *socket) = 0;
virtual int32_t getInitFlags(int32_t instanceNum) = 0;
virtual void onPremiumFloodWait(int32_t instanceNum, int32_t requestToken, bool isUpload) = 0;
virtual void onIntegrityCheckClassic(int32_t instanceNum, int32_t requestToken, std::string project, std::string nonce) = 0;
virtual void onCaptchaCheck(int32_t instanceNum, int32_t requestToken, std::string action, std::string key_id) = 0;
} ConnectiosManagerDelegate;
typedef struct HandshakeDelegate {
virtual void onHandshakeComplete(Handshake *handshake, int64_t keyId, ByteArray *authKey, int32_t timeDifference) = 0;
} HandshakeDelegate;
#define AllConnectionTypes ConnectionTypeGeneric | ConnectionTypeDownload | ConnectionTypeUpload
enum RequestFlag {
RequestFlagEnableUnauthorized = 1,
RequestFlagFailOnServerErrors = 2,
RequestFlagCanCompress = 4,
RequestFlagWithoutLogin = 8,
RequestFlagTryDifferentDc = 16,
RequestFlagForceDownload = 32,
RequestFlagInvokeAfter = 64,
RequestFlagNeedQuickAck = 128,
RequestFlagUseUnboundKey = 256,
RequestFlagResendAfter = 512,
RequestFlagIgnoreFloodWait = 1024,
RequestFlagListenAfterCancel = 2048,
RequestFlagIsCancel = 32768,
RequestFlagFailOnServerErrorsExceptFloodWait = 65536
};
inline std::string to_string_int32(int32_t value) {
char buf[30];
int len = sprintf(buf, "%d", value);
return std::string(buf, (uint32_t) len);
}
inline std::string to_string_uint64(uint64_t value) {
char buf[30];
int len = sprintf(buf, "%" PRIu64, value);
return std::string(buf, (uint32_t) len);
}
inline int32_t char2int(char input) {
if (input >= '0' && input <= '9') {
return input - '0';
} else if (input >= 'A' && input <= 'F') {
return (char) (input - 'A' + 10);
} else if (input >= 'a' && input <= 'f') {
return (char) (input - 'a' + 10);
}
return 0;
}
#endif

View file

@ -0,0 +1,50 @@
/*
* 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.
*/
#include <unistd.h>
#include <sys/eventfd.h>
#include "EventObject.h"
#include "Connection.h"
#include "Timer.h"
EventObject::EventObject(void *object, EventObjectType type) {
eventObject = object;
eventType = type;
}
void EventObject::onEvent(uint32_t events) {
switch (eventType) {
case EventObjectTypeConnection: {
Connection *connection = (Connection *) eventObject;
connection->onEvent(events);
break;
}
case EventObjectTypeTimer: {
Timer *timer = (Timer *) eventObject;
timer->onEvent();
break;
}
case EventObjectTypePipe: {
int *pipe = (int *) eventObject;
char ch;
ssize_t size = 1;
while (size > 0) {
size = read(pipe[0], &ch, 1);
}
break;
}
case EventObjectTypeEvent: {
int *eventFd = (int *) eventObject;
uint64_t count;
eventfd_read(eventFd[0], &count);
break;
}
default:
break;
}
}

View file

@ -0,0 +1,26 @@
/*
* 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 EVENTOBJECT_H
#define EVENTOBJECT_H
#include <stdint.h>
#include "Defines.h"
class EventObject {
public:
EventObject(void *object, EventObjectType type);
void onEvent(uint32_t events);
int64_t time;
void *eventObject;
EventObjectType eventType;
};
#endif

View file

@ -0,0 +1,212 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "FileLog.h"
#include "ConnectionsManager.h"
#ifdef ANDROID
#include <android/log.h>
#endif
#ifdef DEBUG_VERSION
bool LOGS_ENABLED = true;
#else
bool LOGS_ENABLED = false;
#endif
bool REF_LOGS_ENABLED = false;
FileLog &FileLog::getInstance() {
static FileLog instance;
return instance;
}
FileLog::FileLog() {
pthread_mutex_init(&mutex, NULL);
}
void FileLog::init(std::string path) {
pthread_mutex_lock(&mutex);
if (path.size() > 0 && logFile == nullptr) {
logFile = fopen(path.c_str(), "w");
}
pthread_mutex_unlock(&mutex);
}
void FileLog::fatal(const char *message, ...) {
if (!LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
struct timeval time_now;
gettimeofday(&time_now, NULL);
struct tm *now = localtime(&time_now.tv_sec);
#ifdef ANDROID
__android_log_vprint(ANDROID_LOG_FATAL, "tgnet", message, argptr);
va_end(argptr);
va_start(argptr, message);
#else
printf("%d-%d %02d:%02d:%02d FATAL ERROR: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
va_end(argptr);
va_start(argptr, message);
#endif
FILE *logFile = getInstance().logFile;
if (logFile) {
fprintf(logFile, "%d-%d %02d:%02d:%02d.%03d FATAL ERROR: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, (int) (time_now.tv_usec / 1000));
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
#ifdef DEBUG_VERSION
abort();
#endif
}
void FileLog::e(const char *message, ...) {
if (!LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
struct timeval time_now;
gettimeofday(&time_now, NULL);
struct tm *now = localtime(&time_now.tv_sec);
#ifdef ANDROID
__android_log_vprint(ANDROID_LOG_ERROR, "tgnet", message, argptr);
va_end(argptr);
va_start(argptr, message);
#else
printf("%d-%d %02d:%02d:%02d error: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
va_end(argptr);
va_start(argptr, message);
#endif
FILE *logFile = getInstance().logFile;
if (logFile) {
fprintf(logFile, "%d-%d %02d:%02d:%02d.%03d error: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, (int) (time_now.tv_usec / 1000));
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
}
void FileLog::w(const char *message, ...) {
if (!LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
struct timeval time_now;
gettimeofday(&time_now, NULL);
struct tm *now = localtime(&time_now.tv_sec);
#ifdef ANDROID
__android_log_vprint(ANDROID_LOG_WARN, "tgnet", message, argptr);
va_end(argptr);
va_start(argptr, message);
#else
printf("%d-%d %02d:%02d:%02d warning: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
va_end(argptr);
va_start(argptr, message);
#endif
FILE *logFile = getInstance().logFile;
if (logFile) {
fprintf(logFile, "%d-%d %02d:%02d:%02d.%03d warning: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, (int) (time_now.tv_usec / 1000));
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
}
void FileLog::d(const char *message, ...) {
if (!LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
struct timeval time_now;
gettimeofday(&time_now, NULL);
struct tm *now = localtime(&time_now.tv_sec);
#ifdef ANDROID
__android_log_vprint(ANDROID_LOG_DEBUG, "tgnet", message, argptr);
va_end(argptr);
va_start(argptr, message);
#else
printf("%d-%d %02d:%02d:%02d debug: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
va_end(argptr);
va_start(argptr, message);
#endif
FILE *logFile = getInstance().logFile;
if (logFile) {
fprintf(logFile, "%d-%d %02d:%02d:%02d.%03d debug: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, (int) (time_now.tv_usec / 1000));
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
}
static int refsCount = 0;
void FileLog::ref(const char *message, ...) {
if (!REF_LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
refsCount++;
#ifdef ANDROID
std::ostringstream s;
s << refsCount << " refs (+ref): " << message;
__android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr);
va_end(argptr);
va_start(argptr, message);
#endif
va_end(argptr);
}
void FileLog::delref(const char *message, ...) {
if (!REF_LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
refsCount--;
#ifdef ANDROID
std::ostringstream s;
s << refsCount << " refs (-ref): " << message;
__android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr);
va_end(argptr);
va_start(argptr, message);
#endif
va_end(argptr);
}

View file

@ -0,0 +1,42 @@
/*
* 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 FILELOG_H
#define FILELOG_H
#include "Defines.h"
class FileLog {
public:
FileLog();
void init(std::string path);
static void fatal(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void e(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void w(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void d(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void ref(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void delref(const char *message, ...) __attribute__((format (printf, 1, 2)));
static FileLog &getInstance();
private:
FILE *logFile = nullptr;
pthread_mutex_t mutex;
};
extern bool LOGS_ENABLED;
#define DEBUG_FATAL FileLog::getInstance().fatal
#define DEBUG_E FileLog::getInstance().e
#define DEBUG_W FileLog::getInstance().w
#define DEBUG_D FileLog::getInstance().d
#define DEBUG_REF FileLog::getInstance().ref
#define DEBUG_DELREF FileLog::getInstance().delref
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
/*
* 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 HANDSHAKE_H
#define HANDSHAKE_H
#include <stdint.h>
#include "Defines.h"
#include <openssl/bn.h>
class Datacenter;
class ByteArray;
class TLObject;
class TL_future_salt;
class Connection;
class Handshake {
public:
Handshake(Datacenter *datacenter, HandshakeType type, HandshakeDelegate *handshakeDelegate);
~Handshake();
void beginHandshake(bool reconnect);
void cleanupHandshake();
void processHandshakeResponse(TLObject *message, int64_t messageId);
void processHandshakeResponse_resPQ(TLObject *message, int64_t messageId);
void processHandshakeResponse_serverDHParams(TLObject *message, int64_t messageId);
void processHandshakeResponse_serverDHParamsAnswer(TLObject *message, int64_t messageId);
void onHandshakeConnectionConnected();
void onHandshakeConnectionClosed();
static void cleanupServerKeys();
HandshakeType getType();
ByteArray *getPendingAuthKey();
int64_t getPendingAuthKeyId();
TLObject *getCurrentHandshakeRequest();
static bool isGoodPrime(BIGNUM *p, uint32_t g);
private:
Datacenter *currentDatacenter;
HandshakeType handshakeType;
HandshakeDelegate *delegate;
uint8_t handshakeState = 0;
TLObject *handshakeRequest = nullptr;
ByteArray *authNonce = nullptr;
ByteArray *authServerNonce = nullptr;
ByteArray *authNewNonce = nullptr;
ByteArray *handshakeAuthKey = nullptr;
TL_future_salt *handshakeServerSalt = nullptr;
int32_t timeDifference = 0;
ByteArray *authKeyTempPending = nullptr;
int64_t authKeyTempPendingId = 0;
int32_t authKeyPendingRequestId = 0;
int64_t authKeyPendingMessageId = 0;
bool needResendData = false;
void sendRequestData(TLObject *object, bool important);
void sendAckRequest(int64_t messageId);
static void saveCdnConfig(Datacenter *datacenter);
static void saveCdnConfigInternal(NativeByteBuffer *buffer);
static void loadCdnConfig(Datacenter *datacenter);
inline Connection *getConnection();
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,923 @@
/*
* 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 MTPROTOSCHEME_H
#define MTPROTOSCHEME_H
#include <vector>
#include <memory>
#include <map>
#include "TLObject.h"
class ByteArray;
class NativeByteBuffer;
class TLClassStore {
public:
static TLObject *TLdeserialize(NativeByteBuffer *stream, uint32_t bytes, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_api_request : public TLObject {
public:
NativeByteBuffer *request = nullptr;
~TL_api_request();
bool isNeedLayer();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t bytes, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_api_response : public TLObject {
public:
std::unique_ptr<NativeByteBuffer> response;
void readParamsEx(NativeByteBuffer *stream, uint32_t bytes, bool &error);
};
class TL_future_salt : public TLObject {
public:
static const uint32_t constructor = 0x0949d9dc;
int32_t valid_since;
int32_t valid_until;
int64_t salt;
static TL_future_salt *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_msgs_state_info : public TLObject {
public:
static const uint32_t constructor = 0x04deb57d;
int64_t req_msg_id;
std::unique_ptr<ByteArray> info;
static TL_msgs_state_info *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class Server_DH_Params : public TLObject {
public:
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce_hash;
std::unique_ptr<ByteArray> encrypted_answer;
static Server_DH_Params *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_server_DH_params_fail : public Server_DH_Params {
public:
static const uint32_t constructor = 0x79cb045d;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_server_DH_params_ok : public Server_DH_Params {
public:
static const uint32_t constructor = 0xd0e8075c;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_resPQ : public TLObject {
public:
static const uint32_t constructor = 0x05162463;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> pq;
std::vector<int64_t> server_public_key_fingerprints;
static TL_resPQ *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
/*
p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data;
p_q_inner_data_temp#3c6a84d4 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data;
*/
class TL_p_q_inner_data : public TLObject {
public:
static const uint32_t constructor = 0x83c95aec;
std::unique_ptr<ByteArray> pq;
std::unique_ptr<ByteArray> p;
std::unique_ptr<ByteArray> q;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_p_q_inner_data_dc : public TLObject {
public:
static const uint32_t constructor = 0xa9f55f95;
std::unique_ptr<ByteArray> pq;
std::unique_ptr<ByteArray> p;
std::unique_ptr<ByteArray> q;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce;
int32_t dc;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_p_q_inner_data_temp : public TLObject {
public:
static const uint32_t constructor = 0x3c6a84d4;
std::unique_ptr<ByteArray> pq;
std::unique_ptr<ByteArray> p;
std::unique_ptr<ByteArray> q;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce;
int32_t expires_in;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_p_q_inner_data_temp_dc : public TLObject {
public:
static const uint32_t constructor = 0x56fddf88;
std::unique_ptr<ByteArray> pq;
std::unique_ptr<ByteArray> p;
std::unique_ptr<ByteArray> q;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce;
int32_t dc;
int32_t expires_in;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_bind_auth_key_inner : public TLObject {
public:
static const uint32_t constructor = 0x75a3f765;
int64_t nonce;
int64_t temp_auth_key_id;
int64_t perm_auth_key_id;
int64_t temp_session_id;
int32_t expires_at;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_auth_bindTempAuthKey : public TLObject {
public:
static const uint32_t constructor = 0xcdd42a05;
int64_t perm_auth_key_id;
int64_t nonce;
int32_t expires_at;
NativeByteBuffer *encrypted_message = nullptr;
~TL_auth_bindTempAuthKey();
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_auth_dropTempAuthKeys : public TLObject {
public:
static const uint32_t constructor = 0x8e48a188;
std::vector<int64_t> except_auth_keys;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_pong : public TLObject {
public:
static const uint32_t constructor = 0x347773c5;
int64_t msg_id;
int64_t ping_id;
static TL_pong *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_future_salts : public TLObject {
public:
static const uint32_t constructor = 0xae500895;
int64_t req_msg_id;
int32_t now;
std::vector<std::unique_ptr<TL_future_salt>> salts;
static TL_future_salts *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class RpcDropAnswer : public TLObject {
public:
int64_t msg_id;
int32_t seq_no;
int32_t bytes;
static RpcDropAnswer *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_rpc_answer_unknown : public RpcDropAnswer {
public:
static const uint32_t constructor = 0x5e2ad36e;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_rpc_answer_dropped : public RpcDropAnswer {
public:
static const uint32_t constructor = 0xa43ad8b7;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_rpc_answer_dropped_running : public RpcDropAnswer {
public:
static const uint32_t constructor = 0xcd78e586;
void serializeToStream(NativeByteBuffer *stream);
};
class Set_client_DH_params_answer : public TLObject {
public:
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> new_nonce_hash2;
std::unique_ptr<ByteArray> new_nonce_hash3;
std::unique_ptr<ByteArray> new_nonce_hash1;
static Set_client_DH_params_answer *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_message : public TLObject {
public:
static const uint32_t constructor = 0x5bb8e511;
int64_t msg_id;
int32_t seqno;
int32_t bytes;
std::unique_ptr<TLObject> body;
TLObject *outgoingBody = nullptr;
std::unique_ptr<NativeByteBuffer> unparsedBody;
static TL_message *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_dh_gen_retry : public Set_client_DH_params_answer {
public:
static const uint32_t constructor = 0x46dc1fb9;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_dh_gen_fail : public Set_client_DH_params_answer {
public:
static const uint32_t constructor = 0xa69dae02;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_dh_gen_ok : public Set_client_DH_params_answer {
public:
static const uint32_t constructor = 0x3bcbf734;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class BadMsgNotification : public TLObject {
public:
int64_t bad_msg_id;
int32_t bad_msg_seqno;
int32_t error_code;
int64_t new_server_salt;
static BadMsgNotification *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_bad_msg_notification : public BadMsgNotification {
public:
static const uint32_t constructor = 0xa7eff811;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_bad_server_salt : public BadMsgNotification {
public:
static const uint32_t constructor = 0xedab447b;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_msgs_state_req : public TLObject {
public:
static const uint32_t constructor = 0xda69fb52;
std::vector<int64_t> msg_ids;
static TL_msgs_state_req *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class MsgDetailedInfo : public TLObject {
public:
int64_t answer_msg_id;
int32_t bytes;
int32_t status;
int64_t msg_id;
static MsgDetailedInfo *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_msg_new_detailed_info : public MsgDetailedInfo {
public:
static const uint32_t constructor = 0x809db6df;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_msg_detailed_info : public MsgDetailedInfo {
public:
static const uint32_t constructor = 0x276d3ec6;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_msg_copy : public TLObject {
public:
static const uint32_t constructor = 0xe06046b2;
std::unique_ptr<TL_message> orig_message;
static TL_msg_copy *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_msgs_all_info : public TLObject {
public:
static const uint32_t constructor = 0x8cc0d131;
std::vector<int64_t> msg_ids;
std::unique_ptr<ByteArray> info;
static TL_msgs_all_info *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_rpc_result : public TLObject {
public:
static const uint32_t constructor = 0xf35c6d01;
int64_t req_msg_id;
std::unique_ptr<TLObject> result;
void readParamsEx(NativeByteBuffer *stream, uint32_t bytes, int32_t instanceNum, bool &error);
};
class TL_new_session_created : public TLObject {
public:
static const uint32_t constructor = 0x9ec20908;
int64_t first_msg_id;
int64_t unique_id;
int64_t server_salt;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class DestroySessionRes : public TLObject {
public:
int64_t session_id;
static DestroySessionRes *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_destroy_session_ok : public DestroySessionRes {
public:
static const uint32_t constructor = 0xe22045fc;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_destroy_session_none : public DestroySessionRes {
public:
static const uint32_t constructor = 0x62d350c9;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_msgs_ack : public TLObject {
public:
static const uint32_t constructor = 0x62d6b459;
std::vector<int64_t> msg_ids;
static TL_msgs_ack *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_msg_container : public TLObject {
public:
static const uint32_t constructor = 0x73f1f8dc;
std::vector<std::unique_ptr<TL_message>> messages;
static TL_msg_container *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_msg_resend_req : public TLObject {
public:
static const uint32_t constructor = 0x7d861a08;
std::vector<int64_t> msg_ids;
static TL_msg_resend_req *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class MsgsStateInfo : public TLObject {
public:
static const uint32_t constructor = 0x04deb57d;
int64_t req_msg_id;
std::string info;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class RpcError : public TLObject {
public:
int32_t error_code;
std::string error_message;
int64_t query_id;
};
class TL_rpc_error : public RpcError {
public:
static const uint32_t constructor = 0x2144ca19;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_rpc_req_error : public RpcError {
public:
static const uint32_t constructor = 0x7ae432f5;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_client_DH_inner_data : public TLObject {
public:
static const uint32_t constructor = 0x6643b654;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
int64_t retry_id;
std::unique_ptr<ByteArray> g_b;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_server_DH_inner_data : public TLObject {
public:
static const uint32_t constructor = 0xb5890dba;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
uint32_t g;
std::unique_ptr<ByteArray> dh_prime;
std::unique_ptr<ByteArray> g_a;
int32_t server_time;
static TL_server_DH_inner_data *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_req_pq : public TLObject {
public:
static const uint32_t constructor = 0x60469778;
std::unique_ptr<ByteArray> nonce;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_req_pq_multi : public TLObject {
public:
static const uint32_t constructor = 0xbe7e8ef1;
std::unique_ptr<ByteArray> nonce;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_req_DH_params : public TLObject {
public:
static const uint32_t constructor = 0xd712e4be;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> p;
std::unique_ptr<ByteArray> q;
int64_t public_key_fingerprint;
std::unique_ptr<ByteArray> encrypted_data;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_set_client_DH_params : public TLObject {
public:
static const uint32_t constructor = 0xf5045f1f;
std::unique_ptr<ByteArray> nonce;
std::unique_ptr<ByteArray> server_nonce;
std::unique_ptr<ByteArray> encrypted_data;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_rpc_drop_answer : public TLObject {
public:
static const uint32_t constructor = 0x58e4a740;
int64_t req_msg_id;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_get_future_salts : public TLObject {
public:
static const uint32_t constructor = 0xb921bd04;
int32_t num;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_ping : public TLObject {
public:
static const uint32_t constructor = 0x7abe77ec;
int64_t ping_id;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_ping_delay_disconnect : public TLObject {
public:
static const uint32_t constructor = 0xf3427b8c;
int64_t ping_id;
int32_t disconnect_delay;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_destroy_session : public TLObject {
public:
static const uint32_t constructor = 0xe7512126;
int64_t session_id;
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_gzip_packed : public TLObject {
public:
static const uint32_t constructor = 0x3072cfa1;
NativeByteBuffer *packed_data_to_send = nullptr;
std::unique_ptr<NativeByteBuffer> packed_data;
std::unique_ptr<TLObject> originalRequest;
~TL_gzip_packed();
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_error : public TLObject {
public:
static const uint32_t constructor = 0xc4b9f9bb;
int32_t code;
std::string text;
static TL_error *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_invokeAfterMsg : public TLObject {
public:
static const uint32_t constructor = 0xcb9f372d;
int64_t msg_id;
TLObject *outgoingQuery = nullptr;
std::unique_ptr<TLObject> query;
void serializeToStream(NativeByteBuffer *stream);
};
class invokeWithLayer : public TLObject {
public:
static const uint32_t constructor = 0xda9b0d0d;
int32_t layer;
std::unique_ptr<TLObject> query;
void serializeToStream(NativeByteBuffer *stream);
};
class invokeWithGooglePlayIntegrity : public TLObject {
public:
static const uint32_t constructor = 0x1df92984;
std::string nonce;
std::string token;
std::unique_ptr<TLObject> query;
void serializeToStream(NativeByteBuffer *stream);
};
class invokeWithReCaptcha : public TLObject {
public:
static const uint32_t constructor = 0xadbb0f94;
std::string token;
std::unique_ptr<TLObject> query;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_inputClientProxy : public TLObject {
public:
static const uint32_t constructor = 0x75588b3f;
std::string address;
int32_t port;
void serializeToStream(NativeByteBuffer *stream);
};
class JSONValue : public TLObject {
public:
static JSONValue *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_jsonObjectValue : public TLObject {
public:
static const uint32_t constructor = 0xc0de1bd9;
std::string key;
std::unique_ptr<JSONValue> value;
static TL_jsonObjectValue *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonBool : public JSONValue {
public:
static const uint32_t constructor = 0xc7345e6a;
bool value;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonNull : public JSONValue {
public:
static const uint32_t constructor = 0x3f6d7b68;
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonString : public JSONValue {
public:
static const uint32_t constructor = 0xb71e767a;
std::string value;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonArray : public JSONValue {
public:
static const uint32_t constructor = 0xf7444763;
std::vector<std::unique_ptr<JSONValue>> value;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonObject : public JSONValue {
public:
static const uint32_t constructor = 0x99c1d49d;
std::vector<std::unique_ptr<TL_jsonObjectValue>> value;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_jsonNumber : public JSONValue {
public:
static const uint32_t constructor = 0x2be0dfa4;
double value;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class initConnection : public TLObject {
public:
static const uint32_t constructor = 0xc1cd5ea9;
int32_t flags;
int32_t api_id;
std::string device_model;
std::string system_version;
std::string app_version;
std::string system_lang_code;
std::string lang_pack;
std::string lang_code;
std::unique_ptr<TL_inputClientProxy> proxy;
std::unique_ptr<JSONValue> params;
std::unique_ptr<TLObject> query;
void serializeToStream(NativeByteBuffer *stream);
};
class IpPort : public TLObject {
public:
static IpPort *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_ipPort : public IpPort {
public:
static const int32_t constructor = 0xd433ad73;
std::string ipv4;
uint32_t port;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_ipPortSecret : public IpPort {
public:
static const int32_t constructor = 0x37982646;
std::string ipv4;
uint32_t port;
std::unique_ptr<ByteArray> secret;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_accessPointRule : public TLObject {
public:
static const int32_t constructor = 0x4679b65f;
std::string phone_prefix_rules;
uint32_t dc_id;
std::vector<std::unique_ptr<IpPort>> ips;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
class TL_help_configSimple : public TLObject {
public:
static const uint32_t constructor = 0x5a592a6c;
int32_t date;
int32_t expires;
std::vector<std::unique_ptr<TL_accessPointRule>> rules;
static TL_help_configSimple *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
};
#endif

View file

@ -0,0 +1,710 @@
/*
* 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.
*/
#include <memory.h>
#include <stdlib.h>
#include "NativeByteBuffer.h"
#include "FileLog.h"
#include "ByteArray.h"
#include "ConnectionsManager.h"
#include "BuffersStorage.h"
static int buffersCount = 0;
NativeByteBuffer::NativeByteBuffer(uint32_t size) {
#ifdef ANDROID
if (jclass_ByteBuffer != nullptr) {
JNIEnv *env = 0;
if (javaVm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1);
}
javaByteBuffer = env->CallStaticObjectMethod(jclass_ByteBuffer, jclass_ByteBuffer_allocateDirect, size);
if (javaByteBuffer == nullptr) {
if (LOGS_ENABLED) DEBUG_E("can't create javaByteBuffer");
exit(1);
}
DEBUG_REF("nativebytebuffer");
jobject globalRef = env->NewGlobalRef(javaByteBuffer);
env->DeleteLocalRef(javaByteBuffer);
javaByteBuffer = globalRef;
buffer = (uint8_t *) env->GetDirectBufferAddress(javaByteBuffer);
bufferOwner = false;
} else {
#endif
buffer = new uint8_t[size];
bufferOwner = true;
#ifdef ANDROID
}
#endif
if (buffer == nullptr) {
if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer");
exit(1);
}
_limit = _capacity = size;
}
NativeByteBuffer::NativeByteBuffer(bool calculate) {
calculateSizeOnly = calculate;
}
NativeByteBuffer::NativeByteBuffer(uint8_t *buff, uint32_t length) {
buffer = buff;
sliced = true;
_limit = _capacity = length;
}
NativeByteBuffer::~NativeByteBuffer() {
#ifdef ANDROID
if (javaByteBuffer != nullptr) {
JNIEnv *env = 0;
if (javaVm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1);
}
DEBUG_DELREF("nativebytebuffer");
env->DeleteGlobalRef(javaByteBuffer);
javaByteBuffer = nullptr;
}
#endif
if (bufferOwner && !sliced && buffer != nullptr) {
delete[] buffer;
buffer = nullptr;
}
_limit = _capacity = 0;
}
uint32_t NativeByteBuffer::position() {
return _position;
}
void NativeByteBuffer::position(uint32_t position) {
if (position > _limit) {
return;
}
_position = position;
}
uint32_t NativeByteBuffer::capacity() {
return _capacity;
}
uint32_t NativeByteBuffer::limit() {
return _limit;
}
uint32_t NativeByteBuffer::remaining() {
return _limit - _position;
}
void NativeByteBuffer::clearCapacity() {
if (!calculateSizeOnly) {
return;
}
_capacity = 0;
}
void NativeByteBuffer::limit(uint32_t limit) {
if (limit > _capacity) {
return;
}
if (_position > limit) {
_position = limit;
}
_limit = limit;
}
void NativeByteBuffer::flip() {
_limit = _position;
_position = 0;
}
void NativeByteBuffer::clear() {
_position = 0;
_limit = _capacity;
}
uint8_t *NativeByteBuffer::bytes() {
return buffer;
}
void NativeByteBuffer::rewind() {
_position = 0;
}
void NativeByteBuffer::compact() {
if (_position == _limit) {
return;
}
memmove(buffer, buffer + _position, sizeof(uint8_t) * (_limit - _position));
_position = (_limit - _position);
_limit = _capacity;
}
bool NativeByteBuffer::hasRemaining() {
return _position < _limit;
}
void NativeByteBuffer::skip(uint32_t length) {
if (!calculateSizeOnly) {
if (_position + length > _limit) {
return;
}
_position += length;
} else {
_capacity += length;
}
}
void NativeByteBuffer::writeInt32(int32_t x, bool *error) {
if (!calculateSizeOnly) {
if (_position + 4 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write int32 error");
return;
}
buffer[_position++] = (uint8_t) x;
buffer[_position++] = (uint8_t) (x >> 8);
buffer[_position++] = (uint8_t) (x >> 16);
buffer[_position++] = (uint8_t) (x >> 24);
} else {
_capacity += 4;
}
}
void NativeByteBuffer::writeInt64(int64_t x, bool *error) {
if (!calculateSizeOnly) {
if (_position + 8 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write int64 error");
return;
}
buffer[_position++] = (uint8_t) x;
buffer[_position++] = (uint8_t) (x >> 8);
buffer[_position++] = (uint8_t) (x >> 16);
buffer[_position++] = (uint8_t) (x >> 24);
buffer[_position++] = (uint8_t) (x >> 32);
buffer[_position++] = (uint8_t) (x >> 40);
buffer[_position++] = (uint8_t) (x >> 48);
buffer[_position++] = (uint8_t) (x >> 56);
} else {
_capacity += 8;
}
}
void NativeByteBuffer::writeBool(bool value, bool *error) {
if (!calculateSizeOnly) {
if (value) {
writeInt32(0x997275b5, error);
} else {
writeInt32(0xbc799737, error);
}
} else {
_capacity += 4;
}
}
void NativeByteBuffer::writeBytes(uint8_t *b, uint32_t length, bool *error) {
if (!calculateSizeOnly) {
if (_position + length > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write bytes error");
return;
}
writeBytesInternal(b, 0, length);
} else {
_capacity += length;
}
}
void NativeByteBuffer::writeBytes(uint8_t *b, uint32_t offset, uint32_t length, bool *error) {
if (!calculateSizeOnly) {
if (_position + length > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write bytes error");
return;
}
writeBytesInternal(b, offset, length);
} else {
_capacity += length;
}
}
void NativeByteBuffer::writeBytes(NativeByteBuffer *b, bool *error) {
uint32_t length = b->_limit - b->_position;
if (length == 0) {
return;
}
if (!calculateSizeOnly) {
if (_position + length > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write bytes error");
return;
}
writeBytesInternal(b->buffer + b->_position, 0, length);
b->position(b->limit());
} else {
_capacity += length;
}
}
void NativeByteBuffer::writeBytes(ByteArray *b, bool *error) {
if (!calculateSizeOnly) {
if (_position + b->length > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write bytes error");
return;
}
writeBytesInternal(b->bytes, 0, b->length);
} else {
_capacity += b->length;
}
}
void NativeByteBuffer::writeBytesInternal(uint8_t *b, uint32_t offset, uint32_t length) {
memcpy(buffer + _position, b + offset, sizeof(uint8_t) * length);
_position += length;
}
void NativeByteBuffer::writeByte(uint8_t i, bool *error) {
if (!calculateSizeOnly) {
if (_position + 1 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write byte error");
return;
}
buffer[_position++] = i;
} else {
_capacity += 1;
}
}
void NativeByteBuffer::writeString(std::string s, bool *error) {
writeByteArray((uint8_t *) s.c_str(), (uint32_t) s.length(), error);
}
void NativeByteBuffer::writeByteArray(uint8_t *b, uint32_t offset, uint32_t length, bool *error) {
if (length <= 253) {
if (!calculateSizeOnly) {
if (_position + 1 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write byte array error");
return;
}
buffer[_position++] = (uint8_t) length;
} else {
_capacity += 1;
}
} else {
if (!calculateSizeOnly) {
if (_position + 4 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write byte array error");
return;
}
buffer[_position++] = (uint8_t) 254;
buffer[_position++] = (uint8_t) length;
buffer[_position++] = (uint8_t) (length >> 8);
buffer[_position++] = (uint8_t) (length >> 16);
} else {
_capacity += 4;
}
}
if (!calculateSizeOnly) {
if (_position + length > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write byte array error");
return;
}
writeBytesInternal(b, offset, length);
} else {
_capacity += length;
}
uint32_t addition = (length + (length <= 253 ? 1 : 4)) % 4;
if (addition != 0) {
addition = 4 - addition;
}
if (!calculateSizeOnly && _position + addition > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("write byte array error");
return;
}
for (uint32_t a = 0; a < addition; a++) {
if (!calculateSizeOnly) {
buffer[_position++] = (uint8_t) 0;
} else {
_capacity += 1;
}
}
}
void NativeByteBuffer::writeByteArray(uint8_t *b, uint32_t length, bool *error) {
writeByteArray(b, 0, length, error);
}
void NativeByteBuffer::writeByteArray(NativeByteBuffer *b, bool *error) {
b->rewind();
writeByteArray(b->buffer, 0, b->limit(), error);
}
void NativeByteBuffer::writeByteArray(ByteArray *b, bool *error) {
writeByteArray(b->bytes, 0, b->length, error);
}
void NativeByteBuffer::writeDouble(double d, bool *error) {
int64_t value;
memcpy(&value, &d, sizeof(int64_t));
writeInt64(value, error);
}
void NativeByteBuffer::writeInt32(int32_t x) {
writeInt32(x, nullptr);
}
void NativeByteBuffer::writeInt64(int64_t x) {
writeInt64(x, nullptr);
}
void NativeByteBuffer::writeBool(bool value) {
writeBool(value, nullptr);
}
void NativeByteBuffer::writeBytes(uint8_t *b, uint32_t length) {
writeBytes(b, length, nullptr);
}
void NativeByteBuffer::writeBytes(uint8_t *b, uint32_t offset, uint32_t length) {
writeBytes(b, offset, length, nullptr);
}
void NativeByteBuffer::writeBytes(ByteArray *b) {
writeBytes(b, nullptr);
}
void NativeByteBuffer::writeBytes(NativeByteBuffer *b) {
writeBytes(b, nullptr);
}
void NativeByteBuffer::writeByte(uint8_t i) {
writeByte(i, nullptr);
}
void NativeByteBuffer::writeString(std::string s) {
writeString(s, nullptr);
}
void NativeByteBuffer::writeByteArray(uint8_t *b, uint32_t offset, uint32_t length) {
writeByteArray(b, offset, length, nullptr);
}
void NativeByteBuffer::writeByteArray(uint8_t *b, uint32_t length) {
writeByteArray(b, length, nullptr);
}
void NativeByteBuffer::writeByteArray(NativeByteBuffer *b) {
writeByteArray(b, nullptr);
}
void NativeByteBuffer::writeByteArray(ByteArray *b) {
writeByteArray(b->bytes, b->length, nullptr);
}
void NativeByteBuffer::writeDouble(double d) {
writeDouble(d, nullptr);
}
int32_t NativeByteBuffer::readInt32(bool *error) {
if (_position + 4 > _limit || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read int32 error");
return 0;
}
int32_t result = ((buffer[_position] & 0xff)) |
((buffer[_position + 1] & 0xff) << 8) |
((buffer[_position + 2] & 0xff) << 16) |
((buffer[_position + 3] & 0xff) << 24);
_position += 4;
return result;
}
uint32_t NativeByteBuffer::readUint32(bool *error) {
return (uint32_t) readInt32(error);
}
uint64_t NativeByteBuffer::readUint64(bool *error) {
return (uint64_t) readInt64(error);
}
int32_t NativeByteBuffer::readBigInt32(bool *error) {
if (_position + 4 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read big int32 error");
return 0;
}
int32_t result = ((buffer[_position] & 0xff) << 24) |
((buffer[_position + 1] & 0xff) << 16) |
((buffer[_position + 2] & 0xff) << 8) |
((buffer[_position + 3] & 0xff));
_position += 4;
return result;
}
int64_t NativeByteBuffer::readInt64(bool *error) {
if (_position + 8 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read int64 error");
return 0;
}
int64_t result = ((int64_t) (buffer[_position] & 0xff)) |
((int64_t) (buffer[_position + 1] & 0xff) << 8) |
((int64_t) (buffer[_position + 2] & 0xff) << 16) |
((int64_t) (buffer[_position + 3] & 0xff) << 24) |
((int64_t) (buffer[_position + 4] & 0xff) << 32) |
((int64_t) (buffer[_position + 5] & 0xff) << 40) |
((int64_t) (buffer[_position + 6] & 0xff) << 48) |
((int64_t) (buffer[_position + 7] & 0xff) << 56);
_position += 8;
return result;
}
uint8_t NativeByteBuffer::readByte(bool *error) {
if (_position + 1 > _limit || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte error");
return 0;
}
return buffer[_position++];
}
bool NativeByteBuffer::readBool(bool *error) {
uint32_t consructor = readUint32(error);
if (consructor == 0x997275b5) {
return true;
} else if (consructor == 0xbc799737) {
return false;
}
if (error != nullptr) {
*error = true;
if (LOGS_ENABLED) DEBUG_E("read bool error");
}
return false;
}
void NativeByteBuffer::readBytes(uint8_t *b, uint32_t length, bool *error) {
if (length > _limit - _position || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read bytes error");
return;
}
memcpy(b, buffer + _position, length);
_position += length;
}
ByteArray *NativeByteBuffer::readBytes(uint32_t length, bool *error) {
if (length > _limit - _position || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read bytes error");
return nullptr;
}
ByteArray *byteArray = new ByteArray(length);
memcpy(byteArray->bytes, buffer + _position, sizeof(uint8_t) * length);
_position += length;
return byteArray;
}
std::string NativeByteBuffer::readString(bool *error) {
uint32_t sl = 1;
if (_position + 1 > _limit || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read string error");
return std::string("");
}
uint32_t l = buffer[_position++];
if (l >= 254) {
if (_position + 3 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read string error");
return std::string("");
}
l = buffer[_position] | (buffer[_position + 1] << 8) | (buffer[_position + 2] << 16);
_position += 3;
sl = 4;
}
uint32_t addition = (l + sl) % 4;
if (addition != 0) {
addition = 4 - addition;
}
if (_position + l + addition > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read string error");
return std::string("");
}
std::string result = std::string((const char *) (buffer + _position), l);
_position += l + addition;
return result;
}
ByteArray *NativeByteBuffer::readByteArray(bool *error) {
uint32_t sl = 1;
if (_position + 1 > _limit || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte array error");
return nullptr;
}
uint32_t l = buffer[_position++];
if (l >= 254) {
if (_position + 3 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte array error");
return nullptr;
}
l = buffer[_position] | (buffer[_position + 1] << 8) | (buffer[_position + 2] << 16);
_position += 3;
sl = 4;
}
uint32_t addition = (l + sl) % 4;
if (addition != 0) {
addition = 4 - addition;
}
if (_position + l + addition > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte array error");
return nullptr;
}
ByteArray *result = new ByteArray(l);
memcpy(result->bytes, buffer + _position, sizeof(uint8_t) * l);
_position += l + addition;
return result;
}
NativeByteBuffer *NativeByteBuffer::readByteBuffer(bool copy, bool *error) {
uint32_t sl = 1;
if (_position + 1 > _limit || calculateSizeOnly) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte buffer error");
return nullptr;
}
uint32_t l = buffer[_position++];
if (l >= 254) {
if (_position + 3 > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte buffer error");
return nullptr;
}
l = buffer[_position] | (buffer[_position + 1] << 8) | (buffer[_position + 2] << 16);
_position += 3;
sl = 4;
}
uint32_t addition = (l + sl) % 4;
if (addition != 0) {
addition = 4 - addition;
}
if (_position + l + addition > _limit) {
if (error != nullptr) {
*error = true;
}
if (LOGS_ENABLED) DEBUG_E("read byte buffer error");
return nullptr;
}
NativeByteBuffer *result = nullptr;
if (copy) {
result = BuffersStorage::getInstance().getFreeBuffer(l);
memcpy(result->buffer, buffer + _position, sizeof(uint8_t) * l);
} else {
result = new NativeByteBuffer(buffer + _position, l);
}
_position += l + addition;
return result;
}
double NativeByteBuffer::readDouble(bool *error) {
double value;
int64_t value2 = readInt64(error);
memcpy(&value, &value2, sizeof(double));
return value;
}
void NativeByteBuffer::reuse() {
if (sliced) {
return;
}
BuffersStorage::getInstance().reuseFreeBuffer(this);
}
#ifdef ANDROID
jobject NativeByteBuffer::getJavaByteBuffer() {
if (javaByteBuffer == nullptr && javaVm != nullptr) {
JNIEnv *env = 0;
if (javaVm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1);
}
javaByteBuffer = env->NewDirectByteBuffer(buffer, _capacity);
if (javaByteBuffer == nullptr) {
if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer");
exit(1);
}
DEBUG_REF("nativebytebuffer");
jobject globalRef = env->NewGlobalRef(javaByteBuffer);
env->DeleteLocalRef(javaByteBuffer);
javaByteBuffer = globalRef;
}
return javaByteBuffer;
}
#endif

View file

@ -0,0 +1,107 @@
/*
* 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 NATIVEBYTEBUFFER_H
#define NATIVEBYTEBUFFER_H
#include <stdint.h>
#include <string>
#ifdef ANDROID
#include <jni.h>
#endif
class ByteArray;
class NativeByteBuffer {
public:
NativeByteBuffer(uint32_t size);
NativeByteBuffer(bool calculate);
NativeByteBuffer(uint8_t *buff, uint32_t length);
~NativeByteBuffer();
uint32_t position();
void position(uint32_t position);
uint32_t limit();
void limit(uint32_t limit);
uint32_t capacity();
uint32_t remaining();
bool hasRemaining();
void rewind();
void compact();
void flip();
void clear();
void skip(uint32_t length);
void clearCapacity();
uint8_t *bytes();
void writeInt32(int32_t x, bool *error);
void writeInt64(int64_t x, bool *error);
void writeBool(bool value, bool *error);
void writeBytes(uint8_t *b, uint32_t length, bool *error);
void writeBytes(uint8_t *b, uint32_t offset, uint32_t length, bool *error);
void writeBytes(ByteArray *b, bool *error);
void writeBytes(NativeByteBuffer *b, bool *error);
void writeByte(uint8_t i, bool *error);
void writeString(std::string s, bool *error);
void writeByteArray(uint8_t *b, uint32_t offset, uint32_t length, bool *error);
void writeByteArray(uint8_t *b, uint32_t length, bool *error);
void writeByteArray(NativeByteBuffer *b, bool *error);
void writeByteArray(ByteArray *b, bool *error);
void writeDouble(double d, bool *error);
void writeInt32(int32_t x);
void writeInt64(int64_t x);
void writeBool(bool value);
void writeBytes(uint8_t *b, uint32_t length);
void writeBytes(uint8_t *b, uint32_t offset, uint32_t length);
void writeBytes(ByteArray *b);
void writeBytes(NativeByteBuffer *b);
void writeByte(uint8_t i);
void writeString(std::string s);
void writeByteArray(uint8_t *b, uint32_t offset, uint32_t length);
void writeByteArray(uint8_t *b, uint32_t length);
void writeByteArray(NativeByteBuffer *b);
void writeByteArray(ByteArray *b);
void writeDouble(double d);
uint32_t readUint32(bool *error);
uint64_t readUint64(bool *error);
int32_t readInt32(bool *error);
int32_t readBigInt32(bool *error);
int64_t readInt64(bool *error);
uint8_t readByte(bool *error);
bool readBool(bool *error);
void readBytes(uint8_t *b, uint32_t length, bool *error);
ByteArray *readBytes(uint32_t length, bool *error);
std::string readString(bool *error);
ByteArray *readByteArray(bool *error);
NativeByteBuffer *readByteBuffer(bool copy, bool *error);
double readDouble(bool *error);
void reuse();
#ifdef ANDROID
jobject getJavaByteBuffer();
#endif
private:
void writeBytesInternal(uint8_t *b, uint32_t offset, uint32_t length);
uint8_t *buffer = nullptr;
bool calculateSizeOnly = false;
bool sliced = false;
uint32_t _position = 0;
uint32_t _limit = 0;
uint32_t _capacity = 0;
bool bufferOwner = true;
#ifdef ANDROID
jobject javaByteBuffer = nullptr;
#endif
};
#endif

View file

@ -0,0 +1,21 @@
/*
* 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.
*/
#include "ProxyCheckInfo.h"
#include "ConnectionsManager.h"
#include "FileLog.h"
ProxyCheckInfo::~ProxyCheckInfo() {
#ifdef ANDROID
if (ptr1 != nullptr) {
DEBUG_DELREF("tgnet (2) request ptr1");
jniEnv[instanceNum]->DeleteGlobalRef(ptr1);
ptr1 = nullptr;
}
#endif
}

View file

@ -0,0 +1,41 @@
/*
* 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 PROXYCHECKINFO_H
#define PROXYCHECKINFO_H
#include <sstream>
#include "Defines.h"
#ifdef ANDROID
#include <jni.h>
#endif
class ProxyCheckInfo {
public:
~ProxyCheckInfo();
int32_t connectionNum = 0;
int32_t requestToken = 0;
std::string address;
uint16_t port = 1080;
std::string username;
std::string password;
std::string secret;
int64_t pingId = 0;
onRequestTimeFunc onRequestTime;
int32_t instanceNum = 0;
#ifdef ANDROID
jobject ptr1 = nullptr;
#endif
};
#endif

View file

@ -0,0 +1,93 @@
/*
* 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.
*/
#include <algorithm>
#include "Request.h"
#include "TLObject.h"
#include "MTProtoScheme.h"
#include "ConnectionsManager.h"
#include "Datacenter.h"
#include "Connection.h"
#include "FileLog.h"
Request::Request(int32_t instance, int32_t token, ConnectionType type, uint32_t flags, uint32_t datacenter, onCompleteFunc completeFunc, onQuickAckFunc quickAckFunc, onWriteToSocketFunc writeToSocketFunc, onRequestClearFunc onClearFunc) {
requestToken = token;
connectionType = type;
requestFlags = flags;
datacenterId = datacenter;
onCompleteRequestCallback = completeFunc;
onQuickAckCallback = quickAckFunc;
onWriteToSocketCallback = writeToSocketFunc;
onRequestClearCallback = onClearFunc;
dataType = (uint8_t) (requestFlags >> 24);
instanceNum = instance;
}
Request::~Request() {
if (!completedSent && !disableClearCallback && onRequestClearCallback != nullptr) {
onRequestClearCallback();
}
}
void Request::addRespondMessageId(int64_t id) {
respondsToMessageIds.push_back(messageId);
}
bool Request::respondsToMessageId(int64_t id) {
return messageId == id || std::find(respondsToMessageIds.begin(), respondsToMessageIds.end(), id) != respondsToMessageIds.end();
}
void Request::clear(bool time) {
messageId = 0;
messageSeqNo = 0;
connectionToken = 0;
if (time) {
startTime = 0;
minStartTime = 0;
}
}
void Request::onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t requestMsgId, int32_t dcId) {
if (onCompleteRequestCallback != nullptr && (result != nullptr || error != nullptr)) {
completedSent = true;
onCompleteRequestCallback(result, error, networkType, responseTime, requestMsgId, dcId);
}
}
void Request::onWriteToSocket() {
if (onWriteToSocketCallback != nullptr) {
onWriteToSocketCallback();
}
}
bool Request::hasInitFlag() {
return isInitRequest || isInitMediaRequest;
}
bool Request::isMediaRequest() {
return Connection::isMediaConnectionType(connectionType);
}
bool Request::isCancelRequest() {
return (requestFlags & RequestFlagIsCancel) != 0;
}
bool Request::needInitRequest(Datacenter *datacenter, uint32_t currentVersion) {
bool media = PFS_ENABLED && datacenter != nullptr && isMediaRequest() && datacenter->hasMediaAddress();
return !media && datacenter->lastInitVersion != currentVersion || media && datacenter->lastInitMediaVersion != currentVersion;
}
void Request::onQuickAck() {
if (onQuickAckCallback != nullptr) {
onQuickAckCallback();
}
}
TLObject *Request::getRpcRequest() {
return rpcRequest.get();
}

View file

@ -0,0 +1,83 @@
/*
* 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 REQUEST_H
#define REQUEST_H
#include <stdint.h>
#include <vector>
#include "Defines.h"
#ifdef ANDROID
#include <jni.h>
#endif
class TLObject;
class TL_error;
class Datacenter;
class Request {
public:
Request(int32_t instance, int32_t token, ConnectionType type, uint32_t flags, uint32_t datacenter, onCompleteFunc completeFunc, onQuickAckFunc quickAckFunc, onWriteToSocketFunc writeToSocketFunc, onRequestClearFunc onClearFunc);
~Request();
int64_t messageId = 0;
int32_t messageSeqNo = 0;
uint32_t datacenterId = 0;
uint32_t connectionToken = 0;
int32_t requestToken = 0;
uint32_t retryCount = 0;
bool failedBySalt = false;
int32_t failedByFloodWait = 0;
bool awaitingIntegrityCheck = false;
bool awaitingCaptchaCheck = false;
bool premiumFloodWait = false;
ConnectionType connectionType;
uint32_t requestFlags;
bool completedSent = false;
bool completed = false;
bool cancelled = false;
bool isInitRequest = false;
bool isInitMediaRequest = false;
uint8_t dataType = 0;
int32_t serializedLength = 0;
int32_t startTime = 0;
int64_t startTimeMillis = 0;
int32_t minStartTime = 0;
int32_t lastResendTime = 0;
bool isResending = false;
int32_t instanceNum = 0;
uint32_t serverFailureCount = 0;
TLObject *rawRequest;
std::unique_ptr<TLObject> rpcRequest;
onCompleteFunc onCompleteRequestCallback;
onQuickAckFunc onQuickAckCallback;
onWriteToSocketFunc onWriteToSocketCallback;
bool disableClearCallback = false;
bool doNotClearOnDrop = false;
int32_t clearAfter = 0;
onRequestClearFunc onRequestClearCallback;
void addRespondMessageId(int64_t id);
bool respondsToMessageId(int64_t id);
void clear(bool time);
void onComplete(TLObject *result, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msg_id, int32_t dcId);
void onQuickAck();
void onWriteToSocket();
bool isMediaRequest();
bool isCancelRequest();
bool hasInitFlag();
bool needInitRequest(Datacenter *datacenter, uint32_t currentVersion);
TLObject *getRpcRequest();
private:
std::vector<int64_t> respondsToMessageIds;
};
#endif

View file

@ -0,0 +1,38 @@
/*
* 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.
*/
#include "TLObject.h"
#include "NativeByteBuffer.h"
thread_local NativeByteBuffer *sizeCalculatorBuffer = new NativeByteBuffer(true);
TLObject::~TLObject() {
}
void TLObject::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
}
void TLObject::serializeToStream(NativeByteBuffer *stream) {
}
TLObject *TLObject::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
return nullptr;
}
uint32_t TLObject::getObjectSize() {
sizeCalculatorBuffer->clearCapacity();
serializeToStream(sizeCalculatorBuffer);
return sizeCalculatorBuffer->capacity();
}
bool TLObject::isNeedLayer() {
return false;
}

View file

@ -0,0 +1,30 @@
/*
* 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 TLOBJECT_H
#define TLOBJECT_H
#include <stdint.h>
#include "Defines.h"
class NativeByteBuffer;
class TLObject {
public:
virtual ~TLObject();
virtual void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
virtual void serializeToStream(NativeByteBuffer *stream);
virtual TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
uint32_t getObjectSize();
virtual bool isNeedLayer();
fillParamsFunc initFunc;
};
#endif

View file

@ -0,0 +1,62 @@
/*
* 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.
*/
#include "Timer.h"
#include "FileLog.h"
#include "EventObject.h"
#include "ConnectionsManager.h"
Timer::Timer(int32_t instance, std::function<void()> function) {
eventObject = new EventObject(this, EventObjectTypeTimer);
instanceNum = instance;
callback = function;
}
Timer::~Timer() {
stop();
if (eventObject != nullptr) {
delete eventObject;
eventObject = nullptr;
}
}
void Timer::start() {
if (started || timeout == 0) {
return;
}
started = true;
ConnectionsManager::getInstance(instanceNum).scheduleEvent(eventObject, timeout);
}
void Timer::stop() {
if (!started) {
return;
}
started = false;
ConnectionsManager::getInstance(instanceNum).removeEvent(eventObject);
}
void Timer::setTimeout(uint32_t ms, bool repeat) {
if (ms == timeout) {
return;
}
repeatable = repeat;
timeout = ms;
if (started) {
ConnectionsManager::getInstance(instanceNum).removeEvent(eventObject);
ConnectionsManager::getInstance(instanceNum).scheduleEvent(eventObject, timeout);
}
}
void Timer::onEvent() {
callback();
if (LOGS_ENABLED) DEBUG_D("timer(%p) call", this);
if (started && repeatable && timeout != 0) {
ConnectionsManager::getInstance(instanceNum).scheduleEvent(eventObject, timeout);
}
}

View file

@ -0,0 +1,41 @@
/*
* 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 TIMER_H
#define TIMER_H
#include <stdint.h>
#include <functional>
#include <sys/epoll.h>
class EventObject;
class Timer {
public:
Timer(int32_t instance, std::function<void()> function);
~Timer();
void start();
void stop();
void setTimeout(uint32_t ms, bool repeat);
private:
void onEvent();
bool started = false;
bool repeatable = false;
int32_t instanceNum;
uint32_t timeout = 0;
std::function<void()> callback;
EventObject *eventObject;
friend class EventObject;
};
#endif