Merge commit '35a9a93fc9adfbced4d5f59baf0c72a2f807f28a'

Conflicts:
	td/telegram/Client.cpp
	td/telegram/StickersManager.cpp
	td/telegram/WebPagesManager.cpp
This commit is contained in:
Andrea Cavalli 2020-10-12 16:10:48 +02:00
commit f423fc0d81
33 changed files with 1278 additions and 1368 deletions

View File

@ -97,8 +97,10 @@ if (EMSCRIPTEN)
set(ZLIB_LIBRARIES)
set(ZLIB_INCLUDE_DIR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s MODULARIZE=1 \
-s EXPORT_NAME=\"'createTdwebModule'\" -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -s MEMFS_APPEND_TO_TYPED_ARRAYS=1 -s USE_ZLIB=1 -s \
MODULARIZE=1 -s EXPORT_NAME=\"'createTdwebModule'\" -s WEBSOCKET_URL=\"'wss:#'\" -s EXTRA_EXPORTED_RUNTIME_METHODS=\"['FS','cwrap']\" -lidbfs.js -lworkerfs.js")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -s DEMANGLE_SUPPORT=1 -s ASSERTIONS=1")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -s DEMANGLE_SUPPORT=1 -s ASSERTIONS=1")
@ -111,6 +113,7 @@ if (EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s WASM=1")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --post-js ${CMAKE_CURRENT_SOURCE_DIR}/post.js")
endif()
if (NOT OPENSSL_FOUND)

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
"@babel/plugin-transform-runtime": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@typescript-eslint/eslint-plugin": "^1.7.0",
"acorn": "^6.1.1",
"acorn": "^6.4.1",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.5",
"clean-webpack-plugin": "^2.0.1",
@ -43,8 +43,8 @@
"lint-staged": "^8.1.5",
"prettier": "^1.17.0",
"typescript": "^3.4.5",
"webpack": "4.28.2",
"webpack-cli": "^3.3.1",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"worker-loader": "^2.0.0"
},
"husky": {

View File

@ -169,7 +169,7 @@ class TdClient {
'receive from worker: ',
JSON.parse(
JSON.stringify(response, (key, value) => {
if (key === 'arr') {
if (key === 'arr' || key === 'data') {
return undefined;
}
return value;
@ -233,7 +233,12 @@ class TdClient {
}
for (const key in response) {
const field = response[key];
if (field && typeof field === 'object') {
if (
field &&
typeof field === 'object' &&
key !== 'data' &&
key !== 'arr'
) {
response[key] = this.prepareResponse(field);
}
}
@ -579,7 +584,7 @@ class FileManager {
file_id: info.file.id,
offset: offset
});
log.error(count, size);
//log.error(count, size);
if (!size) {
size = count.count;
} else if (size > count.count) {
@ -593,7 +598,7 @@ class FileManager {
});
res.data = new Blob([res.data]);
res.transaction_id = -2;
log.error(res);
//log.error(res);
return res;
} catch (e) {
log.info('readFilePart failed', info, offset, size, e);

View File

@ -63,18 +63,19 @@ async function initLocalForage() {
async function loadTdlibWasm(onFS, wasmUrl) {
console.log('loadTdlibWasm');
const Module = await import('./prebuilt/release/td_wasm.js');
log.info('got td_wasm.js');
const td_module = await import('./prebuilt/release/td_wasm.js');
const createTdwebModule = td_module.default;
log.info('got td_wasm.js', td_module, createTdwebModule);
let td_wasm = td_wasm_release;
if (wasmUrl) {
td_wasm = wasmUrl;
}
const module = Module.default({
let module = createTdwebModule({
onRuntimeInitialized: () => {
log.info('runtime intialized');
},
instantiateWasm: (imports, successCallback) => {
log.info('start instantiateWasm', td_wasm);
log.info('start instantiateWasm', td_wasm, imports);
const next = instance => {
log.info('finish instantiateWasm');
successCallback(instance);
@ -84,25 +85,22 @@ async function loadTdlibWasm(onFS, wasmUrl) {
},
ENVIROMENT: 'WORKER'
});
onFS(module.FS); // hack
log.info('Wait module');
module = await module;
log.info('Got module', module);
onFS(module.FS);
const TdModule = new Promise((resolve, reject) =>
module.then(m => {
delete m.then;
resolve(m);
})
);
return TdModule;
//onFS(module.FS);
return module;
}
async function loadTdlibAsmjs(onFS) {
console.log('loadTdlibAsmjs');
const Module = await import('./prebuilt/release/td_asmjs.js');
console.log('got td_asm.js');
const createTdwebModule = (await import('./prebuilt/release/td_asmjs.js'))
.default;
console.log('got td_asm.js', createTdwebModule);
const fromFile = 'td_asmjs.js.mem';
const toFile = td_asmjs_mem_release;
const module = Module.default({
let module = createTdwebModule({
onRuntimeInitialized: () => {
console.log('runtime intialized');
},
@ -114,15 +112,12 @@ async function loadTdlibAsmjs(onFS) {
},
ENVIROMENT: 'WORKER'
});
onFS(module.FS);
const TdModule = new Promise((resolve, reject) =>
module.then(m => {
delete m.then;
resolve(m);
})
);
return TdModule;
onFS(module.FS); // hack
log.info('Wait module');
module = await module;
log.info('Got module', module);
//onFS(module.FS);
return module;
}
async function loadTdlib(mode, onFS, wasmUrl) {
@ -620,7 +615,10 @@ class TdClient {
log.info('got TdModule');
this.td_functions = {
td_create: this.TdModule.cwrap('td_emscripten_create', 'number', []),
td_send: this.TdModule.cwrap('td_emscripten_send', null, ['number', 'string']),
td_send: this.TdModule.cwrap('td_emscripten_send', null, [
'number',
'string'
]),
td_execute: this.TdModule.cwrap('td_emscripten_execute', 'string', [
'string'
]),
@ -633,7 +631,11 @@ class TdClient {
})
);
},
td_get_timeout: this.TdModule.cwrap('td_emscripten_get_timeout', 'number', [])
td_get_timeout: this.TdModule.cwrap(
'td_emscripten_get_timeout',
'number',
[]
)
};
//this.onFS(this.TdModule.FS);
this.FS = this.TdModule.FS;

1
post.js Normal file
View File

@ -0,0 +1 @@
createTdwebModule.ready.FS = Module.FS;

View File

@ -982,9 +982,10 @@ loginUrlInfoRequestConfirmation url:string domain:string bot_user_id:int32 reque
//@description Contains information about a message thread
//@chat_id Identifier of the chat to which the message thread belongs
//@message_thread_id Message thread identifier, unique within the chat
//@reply_info Contains information about the message thread
//@messages The messages from which the thread starts. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id)
//@draft_message A draft of a message in the message thread; may be null
messageThreadInfo chat_id:int53 message_thread_id:int53 messages:vector<message> draft_message:draftMessage = MessageThreadInfo;
messageThreadInfo chat_id:int53 message_thread_id:int53 reply_info:messageReplyInfo messages:vector<message> draft_message:draftMessage = MessageThreadInfo;
//@class RichText @description Describes a text object inside an instant-view web page

Binary file not shown.

View File

@ -12,6 +12,7 @@
#include "td/utils/buffer.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Named.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/ScopeGuard.h"

View File

@ -9,6 +9,7 @@
#include "td/mtproto/PacketInfo.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"

View File

@ -153,9 +153,10 @@ class ClientManager::Impl final {
ConcurrentScheduler::emscripten_clear_main_timeout();
}
if (response.request_id == 0 && response.object != nullptr &&
response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
static_cast<const td::td_api::updateAuthorizationState *>(response.object.get())
->authorization_state_->get_id() == td::td_api::authorizationStateClosed::ID) {
response.object->get_id() == td_api::updateAuthorizationState::ID &&
static_cast<const td_api::updateAuthorizationState *>(response.object.get())->authorization_state_->get_id() ==
td_api::authorizationStateClosed::ID) {
auto guard = concurrent_scheduler_->get_main_guard();
auto it = tds_.find(response.client_id);
CHECK(it != tds_.end());
it->second.reset();
@ -239,7 +240,7 @@ class MultiTd : public Actor {
CHECK(td.empty());
string name = "Td";
auto context = std::make_shared<td::ActorContext>();
auto context = std::make_shared<ActorContext>();
auto old_context = set_context(context);
auto old_tag = set_tag(to_string(td_id));
td = create_actor<Td>("Td", std::move(callback), options_);
@ -255,8 +256,8 @@ class MultiTd : public Actor {
}
void close(int32 td_id) {
size_t erased = tds_.erase(td_id);
CHECK(erased > 0);
size_t erased_count = tds_.erase(td_id);
CHECK(erased_count > 0);
}
private:
@ -283,11 +284,15 @@ class TdReceiver {
bool is_updates_locked = false;
if (include_responses) {
is_responses_locked = receive_responses_lock_.exchange(true);
CHECK(!is_responses_locked);
if (is_responses_locked) {
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
}
}
if (include_updates) {
is_updates_locked = receive_updates_lock_.exchange(true);
CHECK(!is_updates_locked);
if (is_updates_locked) {
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
}
}
auto response = receive_unlocked(timeout, include_responses, include_updates);
if (include_updates) {
@ -298,7 +303,8 @@ class TdReceiver {
is_responses_locked = receive_responses_lock_.exchange(false);
CHECK(is_responses_locked);
}
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' ' << response.object.get();
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' '
<< response.object.get();
return response;
}
@ -530,9 +536,9 @@ class ClientManager::Impl final {
Response receive(double timeout, bool include_responses, bool include_updates) {
auto response = receiver_->receive(timeout, include_responses, include_updates);
if (response.request_id == 0 && response.object != nullptr &&
response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
static_cast<const td::td_api::updateAuthorizationState *>(response.object.get())
->authorization_state_->get_id() == td::td_api::authorizationStateClosed::ID) {
response.object->get_id() == td_api::updateAuthorizationState::ID &&
static_cast<const td_api::updateAuthorizationState *>(response.object.get())->authorization_state_->get_id() ==
td_api::authorizationStateClosed::ID) {
auto lock = impls_mutex_.lock_write().move_as_ok();
close_impl(response.client_id);
}

View File

@ -8397,7 +8397,7 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
Dependencies dependencies;
dependencies.user_ids.insert(user_id);
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "user_full");
if (user_full->need_phone_number_privacy_exception && is_user_contact(user_id)) {
user_full->need_phone_number_privacy_exception = false;
@ -8581,7 +8581,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
dependencies.user_ids.insert(participant.user_id);
dependencies.user_ids.insert(participant.inviter_user_id);
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "chat_full");
for (auto &participant : chat_full->participants) {
get_bot_info_force(participant.user_id);
@ -8668,7 +8668,7 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
add_dialog_and_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
dependencies.chat_ids.insert(channel_full->migrated_from_chat_id);
dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "channel_full");
for (auto &user_id : channel_full->bot_user_ids) {
get_bot_info_force(user_id);

View File

@ -43,30 +43,30 @@ void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id) {
}
}
void resolve_dependencies_force(Td *td, const Dependencies &dependencies) {
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source) {
for (auto user_id : dependencies.user_ids) {
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {
LOG(ERROR) << "Can't find " << user_id;
LOG(ERROR) << "Can't find " << user_id << " from " << source;
}
}
for (auto chat_id : dependencies.chat_ids) {
if (chat_id.is_valid() && !td->contacts_manager_->have_chat_force(chat_id)) {
LOG(ERROR) << "Can't find " << chat_id;
LOG(ERROR) << "Can't find " << chat_id << " from " << source;
}
}
for (auto channel_id : dependencies.channel_ids) {
if (channel_id.is_valid() && !td->contacts_manager_->have_channel_force(channel_id)) {
LOG(ERROR) << "Can't find " << channel_id;
LOG(ERROR) << "Can't find " << channel_id << " from " << source;
}
}
for (auto secret_chat_id : dependencies.secret_chat_ids) {
if (secret_chat_id.is_valid() && !td->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
LOG(ERROR) << "Can't find " << secret_chat_id;
LOG(ERROR) << "Can't find " << secret_chat_id << " from " << source;
}
}
for (auto dialog_id : dependencies.dialog_ids) {
if (dialog_id.is_valid() && !td->messages_manager_->have_dialog_force(dialog_id)) {
LOG(ERROR) << "Can't find " << dialog_id;
LOG(ERROR) << "Can't find " << dialog_id << " from " << source;
td->messages_manager_->force_create_dialog(dialog_id, "resolve_dependencies_force");
}
}

View File

@ -32,6 +32,6 @@ void add_dialog_and_dependencies(Dependencies &dependencies, DialogId dialog_id)
void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
void resolve_dependencies_force(Td *td, const Dependencies &dependencies);
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source);
} // namespace td

View File

@ -6,6 +6,7 @@
//
#include "td/telegram/MessageReplyInfo.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/ServerMessageId.h"
#include "td/utils/logging.h"
@ -123,6 +124,23 @@ void MessageReplyInfo::add_reply(DialogId replier_dialog_id, MessageId reply_mes
}
}
td_api::object_ptr<td_api::messageReplyInfo> MessageReplyInfo::get_message_reply_info_object(
ContactsManager *contacts_manager) const {
if (is_empty()) {
return nullptr;
}
vector<UserId> recent_replier_user_ids;
for (auto recent_replier_dialog_id : recent_replier_dialog_ids) {
if (recent_replier_dialog_id.get_type() == DialogType::User) {
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
}
}
return td_api::make_object<td_api::messageReplyInfo>(
reply_count, contacts_manager->get_user_ids_object(recent_replier_user_ids, "get_message_reply_info_object"),
last_read_inbox_message_id.get(), last_read_outbox_message_id.get(), max_message_id.get());
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) {
if (reply_info.is_comment) {
return string_builder << reply_info.reply_count << " comments in " << reply_info.channel_id << " by "

View File

@ -9,6 +9,7 @@
#include "td/telegram/ChannelId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/MessageId.h"
#include "Td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
@ -17,6 +18,8 @@
namespace td {
class ContactsManager;
struct MessageReplyInfo {
int32 reply_count = -1;
int32 pts = -1;
@ -44,6 +47,8 @@ struct MessageReplyInfo {
void add_reply(DialogId replier_dialog_id, MessageId reply_message_id);
td_api::object_ptr<td_api::messageReplyInfo> get_message_reply_info_object(ContactsManager *contacts_manager) const;
template <class StorerT>
void store(StorerT &storer) const {
CHECK(!is_empty());

View File

@ -6576,18 +6576,8 @@ td_api::object_ptr<td_api::messageInteractionInfo> MessagesManager::get_message_
td_api::object_ptr<td_api::messageReplyInfo> reply_info;
if (is_visible_reply_info) {
vector<UserId> recent_replier_user_ids;
for (auto recent_replier_dialog_id : m->reply_info.recent_replier_dialog_ids) {
if (recent_replier_dialog_id.get_type() == DialogType::User) {
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
}
}
reply_info = td_api::make_object<td_api::messageReplyInfo>(
m->reply_info.reply_count,
td_->contacts_manager_->get_user_ids_object(recent_replier_user_ids, "get_message_interaction_info_object"),
m->reply_info.last_read_inbox_message_id.get(), m->reply_info.last_read_outbox_message_id.get(),
m->reply_info.max_message_id.get());
CHECK(reply_info->reply_count_ >= 0);
reply_info = m->reply_info.get_message_reply_info_object(td_->contacts_manager_.get());
CHECK(reply_info != nullptr);
}
return td_api::make_object<td_api::messageInteractionInfo>(m->view_count, m->forward_count, std::move(reply_info));
@ -14456,8 +14446,8 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_scheduled_messag
auto result = treap_delete_message(v);
if (message_id.is_scheduled_server()) {
size_t erased = d->scheduled_message_date.erase(message_id.get_scheduled_server_message_id());
CHECK(erased != 0);
size_t erased_count = d->scheduled_message_date.erase(message_id.get_scheduled_server_message_id());
CHECK(erased_count != 0);
}
cancel_send_deleted_message(d->dialog_id, result.get(), is_permanently_deleted);
@ -14507,7 +14497,7 @@ void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&
add_dialog_dependencies(dependencies, dialog_id);
}
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "load_dialogs");
for (auto dialog_id : dialog_ids) {
if (dialog_id.is_valid()) {
@ -16125,14 +16115,23 @@ td_api::object_ptr<td_api::messageThreadInfo> MessagesManager::get_message_threa
Dialog *d = get_dialog(info.dialog_id);
CHECK(d != nullptr);
td_api::object_ptr<td_api::messageReplyInfo> reply_info;
vector<td_api::object_ptr<td_api::message>> messages;
messages.reserve(info.message_ids.size());
for (auto message_id : info.message_ids) {
auto message = get_message_object(d->dialog_id, get_message_force(d, message_id, "get_message_thread_info_object"));
const Message *m = get_message_force(d, message_id, "get_message_thread_info_object");
auto message = get_message_object(d->dialog_id, m);
if (message != nullptr) {
if (message->interaction_info_ != nullptr && message->interaction_info_->reply_info_ != nullptr) {
reply_info = m->reply_info.get_message_reply_info_object(td_->contacts_manager_.get());
CHECK(reply_info != nullptr);
}
messages.push_back(std::move(message));
}
}
if (reply_info == nullptr) {
return nullptr;
}
MessageId top_thread_message_id;
td_api::object_ptr<td_api::draftMessage> draft_message;
@ -16146,7 +16145,8 @@ td_api::object_ptr<td_api::messageThreadInfo> MessagesManager::get_message_threa
}
}
return td_api::make_object<td_api::messageThreadInfo>(d->dialog_id.get(), top_thread_message_id.get(),
std::move(messages), std::move(draft_message));
std::move(reply_info), std::move(messages),
std::move(draft_message));
}
void MessagesManager::get_dialog_info_full(DialogId dialog_id, Promise<Unit> &&promise) {
@ -20929,8 +20929,8 @@ void MessagesManager::on_get_dialog_message_by_date_success(DialogId dialog_id,
}
void MessagesManager::on_get_dialog_message_by_date_fail(int64 random_id) {
auto erased = get_dialog_message_by_date_results_.erase(random_id);
CHECK(erased > 0);
auto erased_count = get_dialog_message_by_date_results_.erase(random_id);
CHECK(erased_count > 0);
}
tl_object_ptr<td_api::message> MessagesManager::get_dialog_message_by_date_object(int64 random_id) {
@ -21199,7 +21199,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
is_first = false;
pos++;
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "get_history");
if (from_the_end && !last_added_message_id.is_valid() && last_received_message_id < d->first_database_message_id &&
!d->have_full_history) {
@ -21514,7 +21514,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
added_message_ids.push_back(m->message_id);
}
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "get_scheduled_messages");
// for (auto message_id : added_message_ids) {
// send_update_new_message(d, get_message(d, message_id));
@ -30329,7 +30329,7 @@ MessagesManager::Message *MessagesManager::on_get_message_from_database(DialogId
Dependencies dependencies;
add_message_dependencies(dependencies, d->dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "get_message");
m->have_previous = false;
m->have_next = false;
@ -33331,7 +33331,7 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
if (d->draft_message != nullptr) {
add_formatted_text_dependencies(dependencies, &d->draft_message->input_message_text.text);
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "parse_dialog");
return d;
}
@ -34523,7 +34523,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "SendMessageLogEvent");
m->content =
dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send, MessageCopyOptions());
@ -34553,7 +34553,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "SendBotStartMessageLogEvent");
auto bot_user_id = log_event.bot_user_id;
if (!td_->contacts_manager_->have_user_force(bot_user_id)) {
@ -34590,7 +34590,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "SendInlineQueryResultMessageLogEvent");
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::SendViaBot,
MessageCopyOptions());
@ -34619,7 +34619,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "SendScreenshotTakenNotificationMessageLogEvent");
auto result_message = continue_send_message(dialog_id, std::move(m), event.id_);
if (result_message != nullptr) {
@ -34646,7 +34646,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
for (auto &m : messages) {
add_message_dependencies(dependencies, to_dialog_id, m.get());
}
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "ForwardMessagesLogEvent");
Dialog *to_dialog = get_dialog_force(to_dialog_id);
if (to_dialog == nullptr) {
@ -35128,7 +35128,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.dialog_id_;
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "GetDialogFromServerLogEvent");
get_dialog_force(dialog_id); // load it if exists

View File

@ -643,7 +643,7 @@ void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id,
}
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id << " from " << source;
auto &message_ids = poll_messages_[poll_id];
auto is_deleted = message_ids.erase(full_message_id);
auto is_deleted = message_ids.erase(full_message_id) > 0;
LOG_CHECK(is_deleted) << source << " " << poll_id << " " << full_message_id;
if (message_ids.empty()) {
poll_messages_.erase(poll_id);
@ -1653,7 +1653,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "SetPollAnswerLogEvent");
do_set_poll_answer(log_event.poll_id_, log_event.full_message_id_, std::move(log_event.options_), event.id_,
Auto());
@ -1672,7 +1672,7 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id); // do not load the dialog itself
resolve_dependencies_force(td_, dependencies);
resolve_dependencies_force(td_, dependencies, "StopPollLogEvent");
do_stop_poll(log_event.poll_id_, log_event.full_message_id_, nullptr, event.id_, Auto());
break;

View File

@ -3581,8 +3581,8 @@ void StickersManager::unregister_dice(const string &emoji, int32 value, FullMess
LOG(INFO) << "Unregister dice " << emoji << " with value " << value << " from " << full_message_id << " from "
<< source;
auto &message_ids = dice_messages_[emoji];
message_ids.erase(full_message_id);
LOG(INFO) << source << " " << emoji << " " << value << " " << full_message_id;
auto is_deleted = message_ids.erase(full_message_id) > 0;
LOG_CHECK(is_deleted) << source << " " << emoji << " " << value << " " << full_message_id;
if (message_ids.empty()) {
dice_messages_.erase(emoji);

View File

@ -103,7 +103,7 @@ class Td final : public NetQueryCallback {
~Td() override;
struct Options {
std::shared_ptr<td::NetQueryStats> net_query_stats;
std::shared_ptr<NetQueryStats> net_query_stats;
};
Td(unique_ptr<TdCallback> callback, Options options);

View File

@ -741,8 +741,9 @@ void WebPagesManager::unregister_web_page(WebPageId web_page_id, FullMessageId f
if (find_message_ids == web_page_messages_.end()) { return; }
auto &message_ids = find_message_ids->second;
// End custom-patches
auto is_deleted = message_ids.erase(full_message_id);
auto is_deleted = message_ids.erase(full_message_id) > 0;
if (!is_deleted) { return; }
LOG_CHECK(is_deleted) << source << " " << web_page_id << " " << full_message_id;
if (message_ids.empty()) {
web_page_messages_.erase(web_page_id);

View File

@ -13,8 +13,8 @@
#include "td/telegram/ClientActor.h"
#include "td/telegram/Log.h"
#include "td/telegram/td_api_json.h"
#include "td/telegram/Td.h" // for VERBOSITY_NAME(td_requests)
#include "td/telegram/td_api_json.h"
#include "td/utils/base64.h"
#include "td/utils/buffer.h"

View File

@ -11,6 +11,7 @@
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/port/FileFd.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"

View File

@ -2416,7 +2416,7 @@ class FileManager::ForceUploadActor : public Actor {
if (callback_.empty()) {
return;
}
send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, td::Status::Error("Cancelled"));
send_closure(std::move(callback_), &ForceUploadActor::on_upload_error, Status::Error("Cancelled"));
}
private:

View File

@ -15,6 +15,7 @@
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include <memory>

View File

@ -13,6 +13,7 @@
#include "td/utils/Closure.h"
#include "td/utils/Heap.h"
#include "td/utils/List.h"
#include "td/utils/logging.h"
#include "td/utils/MovableValue.h"
#include "td/utils/MpscPollableQueue.h"
#include "td/utils/ObjectPool.h"

View File

@ -7,6 +7,7 @@
#pragma once
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"

View File

@ -368,7 +368,7 @@ class TQueueImpl : public TQueue {
void schedule_queue_gc(QueueId queue_id, Queue &q, int32 gc_at) {
if (q.gc_at != 0) {
bool is_deleted = queue_gc_at_.erase({q.gc_at, queue_id});
bool is_deleted = queue_gc_at_.erase({q.gc_at, queue_id}) > 0;
CHECK(is_deleted);
}
q.gc_at = gc_at;

View File

@ -272,6 +272,7 @@ if (TDUTILS_MIME_TYPE)
endif()
set(TDUTILS_TEST_SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/test/bitmask.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp

View File

@ -472,8 +472,8 @@ void FileFd::remove_local_lock(const string &path) {
if (!path.empty()) {
VLOG(fd) << "Unlock file \"" << path << '"';
std::unique_lock<std::mutex> lock(in_process_lock_mutex);
auto erased = locked_files.erase(path);
CHECK(erased > 0);
auto erased_count = locked_files.erase(path);
CHECK(erased_count > 0);
}
}

246
tdutils/test/bitmask.cpp Normal file
View File

@ -0,0 +1,246 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/utils/tests.h"
#include "td/utils/misc.h"
#include "td/utils/utf8.h"
namespace td {
class RangeSet {
template <class T>
static auto find(T &ranges, int64 begin) {
return std::lower_bound(ranges.begin(), ranges.end(), begin,
[](const Range &range, int64 begin) { return range.end < begin; });
}
auto find(int64 begin) const {
return find(ranges_, begin);
}
auto find(int64 begin) {
return find(ranges_, begin);
}
public:
struct Range {
int64 begin;
int64 end;
};
static constexpr int64 BitSize = 1024;
static constexpr int64 MaxPartSize = 16 * 1024 * 1024;
RangeSet() = default;
static RangeSet create_one_range(int64 end, int64 begin = 0) {
RangeSet res;
res.ranges_.push_back({begin, end});
return res;
}
static td::Result<RangeSet> decode(CSlice data) {
if (!check_utf8(data)) {
return Status::Error("Invalid encoding");
}
uint32 curr = 0;
bool is_empty = false;
RangeSet res;
for (auto begin = data.ubegin(); begin != data.uend();) {
uint32 size;
begin = next_utf8_unsafe(begin, &size, "RangeSet");
if (!is_empty && size != 0) {
res.ranges_.push_back({curr * BitSize, (curr + size) * BitSize});
}
curr += size;
is_empty = !is_empty;
}
return res;
}
std::string encode(int64 prefix_size = -1) const {
std::vector<uint32> sizes;
uint32 all_end = 0;
if (prefix_size != -1) {
prefix_size = (prefix_size + BitSize - 1) / BitSize * BitSize;
}
for (auto it : ranges_) {
if (prefix_size != -1 && it.begin >= prefix_size) {
break;
}
if (prefix_size != -1 && it.end > prefix_size) {
it.end = prefix_size;
}
CHECK(it.begin % BitSize == 0);
CHECK(it.end % BitSize == 0);
uint32 begin = narrow_cast<uint32>(it.begin / BitSize);
uint32 end = narrow_cast<uint32>(it.end / BitSize);
if (sizes.empty()) {
if (begin != 0) {
sizes.push_back(0);
sizes.push_back(begin);
}
} else {
sizes.push_back(begin - all_end);
}
sizes.push_back(end - begin);
all_end = end;
}
std::string res;
for (auto c : sizes) {
append_utf8_character(res, c);
}
return res;
}
int64 get_ready_prefix_size(int64 offset, int64 file_size = -1) const {
auto it = find(offset);
if (it == ranges_.end()) {
return 0;
}
if (it->begin > offset) {
return 0;
}
CHECK(offset >= it->begin);
CHECK(offset <= it->end);
auto end = it->end;
if (file_size != -1 && end > file_size) {
end = file_size;
}
if (end < offset) {
return 0;
}
return end - offset;
}
int64 get_total_size(int64 file_size) const {
int64 res = 0;
for (auto it : ranges_) {
if (it.begin >= file_size) {
break;
}
if (it.end > file_size) {
it.end = file_size;
}
res += it.end - it.begin;
}
return res;
}
int64 get_ready_parts(int64 offset_part, int64 part_size) const {
auto offset = offset_part * part_size;
auto it = find(offset);
if (it == ranges_.end()) {
return 0;
}
if (it->begin > offset) {
return 0;
}
return (it->end - offset) / part_size;
}
bool is_ready(int64 begin, int64 end) const {
auto it = find(begin);
if (it == ranges_.end()) {
return false;
}
return it->begin <= begin && end <= it->end;
}
void set(int64 begin, int64 end) {
CHECK(begin % BitSize == 0);
CHECK(end % BitSize == 0);
// 1. skip all with r.end < begin
auto it_begin = find(begin);
// 2. combine with all r.begin <= end
auto it_end = it_begin;
for (; it_end != ranges_.end() && it_end->begin <= end; ++it_end) {
}
if (it_begin == it_end) {
ranges_.insert(it_begin, Range{begin, end});
} else {
begin = std::min(begin, it_begin->begin);
--it_end;
end = std::max(end, it_end->end);
*it_end = Range{begin, end};
ranges_.erase(it_begin, it_end);
}
}
std::vector<int32> as_vector(int32 part_size) const {
std::vector<int32> res;
for (auto it : ranges_) {
auto begin = narrow_cast<int32>((it.begin + part_size - 1) / part_size);
auto end = narrow_cast<int32>(it.end / part_size);
while (begin < end) {
res.push_back(begin++);
}
}
return res;
}
private:
std::vector<Range> ranges_;
};
TEST(Bitmask, simple) {
auto validate_encoding = [](auto &rs) {
auto str = rs.encode();
LOG(ERROR) << str.size();
RangeSet rs2 = RangeSet::decode(str).move_as_ok();
auto str2 = rs2.encode();
rs = std::move(rs2);
CHECK(str2 == str);
};
{
RangeSet rs;
int32 S = 128 * 1024;
int32 O = S * 5000;
for (int i = 1; i < 30; i++) {
if (i % 2 == 0) {
rs.set(O + S * i, O + S * (i + 1));
}
}
validate_encoding(rs);
}
{
RangeSet rs;
int32 S = 1024;
auto get = [&](auto p) {
return rs.get_ready_prefix_size(p * S) / S;
};
auto set = [&](auto l, auto r) {
rs.set(l * S, r * S);
validate_encoding(rs);
ASSERT_TRUE(rs.is_ready(l * S, r * S));
ASSERT_TRUE(get(l) >= (r - l));
};
set(6, 7);
ASSERT_EQ(1, get(6));
ASSERT_EQ(0, get(5));
set(8, 9);
ASSERT_EQ(0, get(7));
set(7, 8);
ASSERT_EQ(2, get(7));
ASSERT_EQ(3, get(6));
set(3, 5);
ASSERT_EQ(1, get(4));
set(4, 6);
ASSERT_EQ(5, get(4));
set(10, 11);
set(9, 10);
ASSERT_EQ(8, get(3));
set(14, 16);
set(12, 13);
ASSERT_EQ(8, get(3));
ASSERT_EQ(10, rs.get_ready_prefix_size(S * 3, S * 3 + 10));
ASSERT_TRUE(!rs.is_ready(S*11, S *12));
ASSERT_EQ(3, rs.get_ready_parts(2, S * 2));
ASSERT_EQ(std::vector<int32>({2, 3, 4, 7}), rs.as_vector(S * 2) );
}
}
} // namespace td

View File

@ -32,12 +32,16 @@ target_link_libraries(all_tests PRIVATE tdcore tdclient)
if (NOT CMAKE_CROSSCOMPILING OR EMSCRIPTEN)
#Tests
add_executable(test-tdutils ${TESTS_MAIN} ${TDUTILS_TEST_SOURCE})
add_executable(run_all_tests ${TESTS_MAIN} ${TD_TEST_SOURCE})
if (CLANG AND NOT CYGWIN AND NOT EMSCRIPTEN AND NOT (CMAKE_HOST_SYSTEM_NAME MATCHES "OpenBSD"))
target_compile_options(test-tdutils PUBLIC -fsanitize=undefined -fno-sanitize=vptr)
target_compile_options(run_all_tests PUBLIC -fsanitize=undefined -fno-sanitize=vptr)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fno-sanitize=vptr")
endif()
target_include_directories(run_all_tests PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_include_directories(test-tdutils PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(test-tdutils PRIVATE tdutils)
target_link_libraries(run_all_tests PRIVATE tdcore tdclient)
if (CLANG)

View File

@ -35,6 +35,7 @@
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <utility>
@ -1008,8 +1009,8 @@ TEST(Client, Close) {
receive_count++;
{
std::unique_lock<std::mutex> guard(request_ids_mutex);
size_t erase_count = request_ids.erase(response.id);
CHECK(erase_count > 0);
size_t erased_count = request_ids.erase(response.id);
CHECK(erased_count > 0);
}
}
if (can_stop_receive && receive_count == send_count) {
@ -1070,8 +1071,8 @@ TEST(Client, ManagerClose) {
receive_count++;
{
std::unique_lock<std::mutex> guard(request_ids_mutex);
size_t erase_count = request_ids.erase(response.request_id);
CHECK(erase_count > 0);
size_t erased_count = request_ids.erase(response.request_id);
CHECK(erased_count > 0);
}
}
if (can_stop_receive && receive_count == send_count) {