Merge commit '1cfa7545c938212b8976eafe3055fe161b8fd7c4'
Conflicts: td/telegram/Client.cpp
This commit is contained in:
commit
ef9e05a805
@ -619,24 +619,21 @@ class TdClient {
|
|||||||
this.TdModule = await loadTdlib(mode, this.onFS, options.wasmUrl);
|
this.TdModule = await loadTdlib(mode, this.onFS, options.wasmUrl);
|
||||||
log.info('got TdModule');
|
log.info('got TdModule');
|
||||||
this.td_functions = {
|
this.td_functions = {
|
||||||
td_create: this.TdModule.cwrap('td_create', 'number', []),
|
td_create: this.TdModule.cwrap('td_emscripten_create', 'number', []),
|
||||||
td_destroy: this.TdModule.cwrap('td_destroy', null, ['number']),
|
td_send: this.TdModule.cwrap('td_emscripten_send', null, ['number', 'string']),
|
||||||
td_send: this.TdModule.cwrap('td_send', null, ['number', 'string']),
|
td_execute: this.TdModule.cwrap('td_emscripten_execute', 'string', [
|
||||||
td_execute: this.TdModule.cwrap('td_execute', 'string', [
|
|
||||||
'number',
|
|
||||||
'string'
|
'string'
|
||||||
]),
|
]),
|
||||||
td_receive: this.TdModule.cwrap('td_receive', 'string', ['number']),
|
td_receive: this.TdModule.cwrap('td_emscripten_receive', 'string', []),
|
||||||
td_set_verbosity: verbosity => {
|
td_set_verbosity: verbosity => {
|
||||||
this.td_functions.td_execute(
|
this.td_functions.td_execute(
|
||||||
0,
|
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
'@type': 'setLogVerbosityLevel',
|
'@type': 'setLogVerbosityLevel',
|
||||||
new_verbosity_level: verbosity
|
new_verbosity_level: verbosity
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
td_get_timeout: this.TdModule.cwrap('td_get_timeout', 'number', [])
|
td_get_timeout: this.TdModule.cwrap('td_emscripten_get_timeout', 'number', [])
|
||||||
};
|
};
|
||||||
//this.onFS(this.TdModule.FS);
|
//this.onFS(this.TdModule.FS);
|
||||||
this.FS = this.TdModule.FS;
|
this.FS = this.TdModule.FS;
|
||||||
@ -849,7 +846,7 @@ class TdClient {
|
|||||||
|
|
||||||
execute(query) {
|
execute(query) {
|
||||||
try {
|
try {
|
||||||
const res = this.td_functions.td_execute(0, JSON.stringify(query));
|
const res = this.td_functions.td_execute(JSON.stringify(query));
|
||||||
const response = JSON.parse(res);
|
const response = JSON.parse(res);
|
||||||
this.callback(response);
|
this.callback(response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -863,7 +860,7 @@ class TdClient {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
const msg = this.td_functions.td_receive(this.client);
|
const msg = this.td_functions.td_receive();
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -117,11 +117,7 @@ class ClientManager::Impl final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void send(ClientId client_id, RequestId request_id, td_api::object_ptr<td_api::Function> &&request) {
|
void send(ClientId client_id, RequestId request_id, td_api::object_ptr<td_api::Function> &&request) {
|
||||||
Request request;
|
requests_.push_back({client_id, request_id, std::move(request)});
|
||||||
request.client_id = client_id;
|
|
||||||
request.id = request_id;
|
|
||||||
request.request = std::move(request);
|
|
||||||
requests_.push_back(std::move(request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Response receive(double timeout) {
|
Response receive(double timeout) {
|
||||||
@ -131,10 +127,20 @@ class ClientManager::Impl final {
|
|||||||
Response receive(double timeout, bool include_responses, bool include_updates) {
|
Response receive(double timeout, bool include_responses, bool include_updates) {
|
||||||
if (!requests_.empty()) {
|
if (!requests_.empty()) {
|
||||||
auto guard = concurrent_scheduler_->get_main_guard();
|
auto guard = concurrent_scheduler_->get_main_guard();
|
||||||
for (auto &request : requests_) {
|
for (size_t i = 0; i < requests_.size(); i++) {
|
||||||
auto &td = tds_[request.client_id];
|
auto &request = requests_[i];
|
||||||
CHECK(!td.empty());
|
if (request.client_id <= 0 || request.client_id > client_id_) {
|
||||||
send_closure_later(td, &Td::request, request.id, std::move(request.request));
|
receiver_->add_response(request.client_id, request.id,
|
||||||
|
td_api::make_object<td_api::error>(400, "Invalid TDLib instance specified"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto it = tds_.find(request.client_id);
|
||||||
|
if (it == tds_.end() || it->second.empty()) {
|
||||||
|
receiver_->add_response(request.client_id, request.id,
|
||||||
|
td_api::make_object<td_api::error>(500, "Request aborted"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
send_closure_later(it->second, &Td::request, request.id, std::move(request.request));
|
||||||
}
|
}
|
||||||
requests_.clear();
|
requests_.clear();
|
||||||
}
|
}
|
||||||
@ -146,9 +152,21 @@ class ClientManager::Impl final {
|
|||||||
} else {
|
} else {
|
||||||
ConcurrentScheduler::emscripten_clear_main_timeout();
|
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) {
|
||||||
|
auto it = tds_.find(response.client_id);
|
||||||
|
CHECK(it != tds_.end());
|
||||||
|
it->second.reset();
|
||||||
|
}
|
||||||
if (response.object == nullptr && response.client_id != 0 && response.request_id == 0) {
|
if (response.object == nullptr && response.client_id != 0 && response.request_id == 0) {
|
||||||
auto guard = concurrent_scheduler_->get_main_guard();
|
auto guard = concurrent_scheduler_->get_main_guard();
|
||||||
tds_.erase(response.client_id);
|
auto it = tds_.find(response.client_id);
|
||||||
|
CHECK(it != tds_.end());
|
||||||
|
CHECK(it->second.empty());
|
||||||
|
tds_.erase(it);
|
||||||
|
response.client_id = 0;
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -161,7 +179,7 @@ class ClientManager::Impl final {
|
|||||||
{
|
{
|
||||||
auto guard = concurrent_scheduler_->get_main_guard();
|
auto guard = concurrent_scheduler_->get_main_guard();
|
||||||
for (auto &td : tds_) {
|
for (auto &td : tds_) {
|
||||||
td.second = {};
|
td.second.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!tds_.empty()) {
|
while (!tds_.empty()) {
|
||||||
@ -177,7 +195,7 @@ class ClientManager::Impl final {
|
|||||||
RequestId id;
|
RequestId id;
|
||||||
td_api::object_ptr<td_api::Function> request;
|
td_api::object_ptr<td_api::Function> request;
|
||||||
};
|
};
|
||||||
td::vector<Request> requests_;
|
vector<Request> requests_;
|
||||||
unique_ptr<ConcurrentScheduler> concurrent_scheduler_;
|
unique_ptr<ConcurrentScheduler> concurrent_scheduler_;
|
||||||
ClientId client_id_{0};
|
ClientId client_id_{0};
|
||||||
Td::Options options_;
|
Td::Options options_;
|
||||||
@ -186,12 +204,11 @@ class ClientManager::Impl final {
|
|||||||
|
|
||||||
class Client::Impl final {
|
class Client::Impl final {
|
||||||
public:
|
public:
|
||||||
Impl() {
|
Impl() : client_id_(impl_.create_client()) {
|
||||||
client_id_ = impl_.create_client();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(Request request) {
|
void send(Request request) {
|
||||||
impl_.send(client_id_, request.id, std::move(request.request));
|
impl_.send(client_id_, request.id, std::move(request.function));
|
||||||
}
|
}
|
||||||
|
|
||||||
Response receive(double timeout) {
|
Response receive(double timeout) {
|
||||||
@ -201,7 +218,7 @@ class Client::Impl final {
|
|||||||
Response receive(double timeout, bool include_responses, bool include_updates) {
|
Response receive(double timeout, bool include_responses, bool include_updates) {
|
||||||
auto response = impl_.receive(timeout, include_responses, include_updates);
|
auto response = impl_.receive(timeout, include_responses, include_updates);
|
||||||
Response old_response;
|
Response old_response;
|
||||||
old_response.id = response.id;
|
old_response.id = response.request_id;
|
||||||
old_response.object = std::move(response.object);
|
old_response.object = std::move(response.object);
|
||||||
return old_response;
|
return old_response;
|
||||||
}
|
}
|
||||||
@ -238,8 +255,8 @@ class MultiTd : public Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close(int32 td_id) {
|
void close(int32 td_id) {
|
||||||
// no check that td_id hasn't been deleted before
|
size_t erased = tds_.erase(td_id);
|
||||||
tds_.erase(td_id);
|
CHECK(erased > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -410,6 +427,10 @@ class MultiImpl {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_valid_client_id(int32 client_id) {
|
||||||
|
return client_id > 0 && client_id < current_id_.load();
|
||||||
|
}
|
||||||
|
|
||||||
void send(ClientManager::ClientId client_id, ClientManager::RequestId request_id,
|
void send(ClientManager::ClientId client_id, ClientManager::RequestId request_id,
|
||||||
td_api::object_ptr<td_api::Function> &&request) {
|
td_api::object_ptr<td_api::Function> &&request) {
|
||||||
auto guard = concurrent_scheduler_->get_send_guard();
|
auto guard = concurrent_scheduler_->get_send_guard();
|
||||||
@ -436,9 +457,10 @@ class MultiImpl {
|
|||||||
thread scheduler_thread_;
|
thread scheduler_thread_;
|
||||||
ActorOwn<MultiTd> multi_td_;
|
ActorOwn<MultiTd> multi_td_;
|
||||||
|
|
||||||
|
static std::atomic<int32> current_id_;
|
||||||
|
|
||||||
static int32 create_id() {
|
static int32 create_id() {
|
||||||
static std::atomic<int32> current_id{1};
|
return current_id_.fetch_add(1);
|
||||||
return current_id.fetch_add(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void create(int32 td_id, unique_ptr<TdCallback> callback) {
|
void create(int32 td_id, unique_ptr<TdCallback> callback) {
|
||||||
@ -447,6 +469,8 @@ class MultiImpl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::atomic<int32> MultiImpl::current_id_{1};
|
||||||
|
|
||||||
class MultiImplPool {
|
class MultiImplPool {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<MultiImpl> get() {
|
std::shared_ptr<MultiImpl> get() {
|
||||||
@ -458,12 +482,12 @@ class MultiImplPool {
|
|||||||
}
|
}
|
||||||
auto &impl = *std::min_element(impls_.begin(), impls_.end(),
|
auto &impl = *std::min_element(impls_.begin(), impls_.end(),
|
||||||
[](auto &a, auto &b) { return a.lock().use_count() < b.lock().use_count(); });
|
[](auto &a, auto &b) { return a.lock().use_count() < b.lock().use_count(); });
|
||||||
auto res = impl.lock();
|
auto result = impl.lock();
|
||||||
if (!res) {
|
if (!result) {
|
||||||
res = std::make_shared<MultiImpl>(net_query_stats_);
|
result = std::make_shared<MultiImpl>(net_query_stats_);
|
||||||
impl = res;
|
impl = result;
|
||||||
}
|
}
|
||||||
return res;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -479,20 +503,24 @@ class ClientManager::Impl final {
|
|||||||
auto client_id = impl->create(*receiver_);
|
auto client_id = impl->create(*receiver_);
|
||||||
{
|
{
|
||||||
auto lock = impls_mutex_.lock_write().move_as_ok();
|
auto lock = impls_mutex_.lock_write().move_as_ok();
|
||||||
impls_[client_id] = std::move(impl);
|
impls_[client_id].impl = std::move(impl);
|
||||||
}
|
}
|
||||||
return client_id;
|
return client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(ClientId client_id, RequestId request_id, td_api::object_ptr<td_api::Function> &&request) {
|
void send(ClientId client_id, RequestId request_id, td_api::object_ptr<td_api::Function> &&request) {
|
||||||
auto lock = impls_mutex_.lock_read().move_as_ok();
|
auto lock = impls_mutex_.lock_read().move_as_ok();
|
||||||
auto it = impls_.find(client_id);
|
if (!MultiImpl::is_valid_client_id(client_id)) {
|
||||||
if (it == impls_.end()) {
|
|
||||||
receiver_->add_response(client_id, request_id,
|
receiver_->add_response(client_id, request_id,
|
||||||
td_api::make_object<td_api::error>(400, "Invalid TDLib instance specified"));
|
td_api::make_object<td_api::error>(400, "Invalid TDLib instance specified"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
it->second->send(client_id, request_id, std::move(request));
|
auto it = impls_.find(client_id);
|
||||||
|
if (it == impls_.end() || it->second.is_closed) {
|
||||||
|
receiver_->add_response(client_id, request_id, td_api::make_object<td_api::error>(500, "Request aborted"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
it->second.impl->send(client_id, request_id, std::move(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
Response receive(double timeout) {
|
Response receive(double timeout) {
|
||||||
@ -501,13 +529,33 @@ class ClientManager::Impl final {
|
|||||||
|
|
||||||
Response receive(double timeout, bool include_responses, bool include_updates) {
|
Response receive(double timeout, bool include_responses, bool include_updates) {
|
||||||
auto response = receiver_->receive(timeout, include_responses, 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) {
|
||||||
|
auto lock = impls_mutex_.lock_write().move_as_ok();
|
||||||
|
close_impl(response.client_id);
|
||||||
|
}
|
||||||
if (response.object == nullptr && response.client_id != 0 && response.request_id == 0) {
|
if (response.object == nullptr && response.client_id != 0 && response.request_id == 0) {
|
||||||
auto lock = impls_mutex_.lock_write().move_as_ok();
|
auto lock = impls_mutex_.lock_write().move_as_ok();
|
||||||
impls_.erase(response.client_id);
|
auto it = impls_.find(response.client_id);
|
||||||
|
CHECK(it != impls_.end());
|
||||||
|
CHECK(it->second.is_closed);
|
||||||
|
impls_.erase(it);
|
||||||
|
response.client_id = 0;
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void close_impl(ClientId client_id) {
|
||||||
|
auto it = impls_.find(client_id);
|
||||||
|
CHECK(it != impls_.end());
|
||||||
|
if (!it->second.is_closed) {
|
||||||
|
it->second.is_closed = true;
|
||||||
|
it->second.impl->close(client_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Impl() = default;
|
Impl() = default;
|
||||||
Impl(const Impl &) = delete;
|
Impl(const Impl &) = delete;
|
||||||
Impl &operator=(const Impl &) = delete;
|
Impl &operator=(const Impl &) = delete;
|
||||||
@ -515,7 +563,7 @@ class ClientManager::Impl final {
|
|||||||
Impl &operator=(Impl &&) = delete;
|
Impl &operator=(Impl &&) = delete;
|
||||||
~Impl() {
|
~Impl() {
|
||||||
for (auto &it : impls_) {
|
for (auto &it : impls_) {
|
||||||
it.second->close(it.first);
|
close_impl(it.first);
|
||||||
}
|
}
|
||||||
while (!impls_.empty()) {
|
while (!impls_.empty()) {
|
||||||
receive(10, false, true);
|
receive(10, false, true);
|
||||||
@ -525,7 +573,11 @@ class ClientManager::Impl final {
|
|||||||
private:
|
private:
|
||||||
MultiImplPool pool_;
|
MultiImplPool pool_;
|
||||||
RwMutex impls_mutex_;
|
RwMutex impls_mutex_;
|
||||||
std::unordered_map<ClientId, std::shared_ptr<MultiImpl>> impls_;
|
struct MultiImplInfo {
|
||||||
|
std::shared_ptr<MultiImpl> impl;
|
||||||
|
bool is_closed = false;
|
||||||
|
};
|
||||||
|
std::unordered_map<ClientId, MultiImplInfo> impls_;
|
||||||
unique_ptr<TdReceiver> receiver_{make_unique<TdReceiver>()};
|
unique_ptr<TdReceiver> receiver_{make_unique<TdReceiver>()};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -538,7 +590,7 @@ class Client::Impl final {
|
|||||||
td_id_ = multi_impl_->create(*receiver_);
|
td_id_ = multi_impl_->create(*receiver_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(Client::Request request) {
|
void send(Request request) {
|
||||||
if (request.id == 0 || request.function == nullptr) {
|
if (request.id == 0 || request.function == nullptr) {
|
||||||
LOG(ERROR) << "Drop wrong request " << request.id;
|
LOG(ERROR) << "Drop wrong request " << request.id;
|
||||||
return;
|
return;
|
||||||
@ -547,17 +599,17 @@ class Client::Impl final {
|
|||||||
multi_impl_->send(td_id_, request.id, std::move(request.function));
|
multi_impl_->send(td_id_, request.id, std::move(request.function));
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Response receive(double timeout) {
|
Response receive(double timeout) {
|
||||||
return receive(timeout, true, true);
|
return receive(timeout, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Response receive(double timeout, bool include_responses, bool include_updates) {
|
Response receive(double timeout, bool include_responses, bool include_updates) {
|
||||||
auto res = receiver_->receive(timeout, include_responses, include_updates);
|
auto response = receiver_->receive(timeout, include_responses, include_updates);
|
||||||
|
|
||||||
Client::Response old_res;
|
Response old_response;
|
||||||
old_res.id = res.request_id;
|
old_response.id = response.request_id;
|
||||||
old_res.object = std::move(res.object);
|
old_response.object = std::move(response.object);
|
||||||
return old_res;
|
return old_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
Impl(const Impl &) = delete;
|
Impl(const Impl &) = delete;
|
||||||
|
@ -114,7 +114,7 @@ void SecretChatsManager::cancel_chat(SecretChatId secret_chat_id, Promise<> prom
|
|||||||
|
|
||||||
void SecretChatsManager::send_message(SecretChatId secret_chat_id, tl_object_ptr<secret_api::decryptedMessage> message,
|
void SecretChatsManager::send_message(SecretChatId secret_chat_id, tl_object_ptr<secret_api::decryptedMessage> message,
|
||||||
tl_object_ptr<telegram_api::InputEncryptedFile> file, Promise<> promise) {
|
tl_object_ptr<telegram_api::InputEncryptedFile> file, Promise<> promise) {
|
||||||
// message->message_ = Random::fast(0, 1) ? string(1, static_cast<char>(0x80)) : "a";
|
// message->message_ = Random::fast_bool() ? string(1, static_cast<char>(0x80)) : "a";
|
||||||
auto actor = get_chat_actor(secret_chat_id.get());
|
auto actor = get_chat_actor(secret_chat_id.get());
|
||||||
auto safe_promise = SafePromise<>(std::move(promise), Status::Error(400, "Can't find secret chat"));
|
auto safe_promise = SafePromise<>(std::move(promise), Status::Error(400, "Can't find secret chat"));
|
||||||
send_closure(actor, &SecretChatActor::send_message, std::move(message), std::move(file), std::move(safe_promise));
|
send_closure(actor, &SecretChatActor::send_message, std::move(message), std::move(file), std::move(safe_promise));
|
||||||
|
@ -1113,7 +1113,7 @@ class CliClient final : public Actor {
|
|||||||
std::tie(excluded_chat_ids, filter) = split(filter);
|
std::tie(excluded_chat_ids, filter) = split(filter);
|
||||||
|
|
||||||
auto rand_bool = [] {
|
auto rand_bool = [] {
|
||||||
return Random::fast(0, 1) == 1;
|
return Random::fast_bool();
|
||||||
};
|
};
|
||||||
|
|
||||||
return td_api::make_object<td_api::chatFilter>(
|
return td_api::make_object<td_api::chatFilter>(
|
||||||
@ -2753,7 +2753,7 @@ class CliClient final : public Actor {
|
|||||||
auto chat = as_chat_id(chat_id);
|
auto chat = as_chat_id(chat_id);
|
||||||
send_request(td_api::make_object<td_api::forwardMessages>(
|
send_request(td_api::make_object<td_api::forwardMessages>(
|
||||||
chat, as_chat_id(from_chat_id), as_message_ids(message_ids), default_message_send_options(), op[0] == 'c',
|
chat, as_chat_id(from_chat_id), as_message_ids(message_ids), default_message_send_options(), op[0] == 'c',
|
||||||
Random::fast(0, 1) == 1));
|
Random::fast_bool()));
|
||||||
} else if (op == "resend") {
|
} else if (op == "resend") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string message_ids;
|
string message_ids;
|
||||||
@ -2777,7 +2777,7 @@ class CliClient final : public Actor {
|
|||||||
} else if (op == "cc" || op == "CreateCall") {
|
} else if (op == "cc" || op == "CreateCall") {
|
||||||
send_request(td_api::make_object<td_api::createCall>(
|
send_request(td_api::make_object<td_api::createCall>(
|
||||||
as_user_id(args), td_api::make_object<td_api::callProtocol>(true, true, 65, 65, vector<string>{"2.6", "3.0"}),
|
as_user_id(args), td_api::make_object<td_api::callProtocol>(true, true, 65, 65, vector<string>{"2.6", "3.0"}),
|
||||||
Random::fast(0, 1) == 1));
|
Random::fast_bool()));
|
||||||
} else if (op == "ac" || op == "AcceptCall") {
|
} else if (op == "ac" || op == "AcceptCall") {
|
||||||
send_request(td_api::make_object<td_api::acceptCall>(
|
send_request(td_api::make_object<td_api::acceptCall>(
|
||||||
as_call_id(args),
|
as_call_id(args),
|
||||||
@ -2790,7 +2790,7 @@ class CliClient final : public Actor {
|
|||||||
std::tie(call_id, is_disconnected) = split(args);
|
std::tie(call_id, is_disconnected) = split(args);
|
||||||
|
|
||||||
send_request(td_api::make_object<td_api::discardCall>(as_call_id(call_id), as_bool(is_disconnected), 0,
|
send_request(td_api::make_object<td_api::discardCall>(as_call_id(call_id), as_bool(is_disconnected), 0,
|
||||||
Random::fast(0, 1) == 1, 0));
|
Random::fast_bool(), 0));
|
||||||
} else if (op == "scr" || op == "SendCallRating") {
|
} else if (op == "scr" || op == "SendCallRating") {
|
||||||
string call_id;
|
string call_id;
|
||||||
string rating;
|
string rating;
|
||||||
@ -3285,8 +3285,7 @@ class CliClient final : public Actor {
|
|||||||
|
|
||||||
td_api::object_ptr<td_api::messageCopyOptions> copy_options;
|
td_api::object_ptr<td_api::messageCopyOptions> copy_options;
|
||||||
if (op == "scopy") {
|
if (op == "scopy") {
|
||||||
copy_options =
|
copy_options = td_api::make_object<td_api::messageCopyOptions>(true, Random::fast_bool(), as_caption("_as_d"));
|
||||||
td_api::make_object<td_api::messageCopyOptions>(true, Random::fast(0, 1) == 0, as_caption("_as_d"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
send_message(chat_id,
|
send_message(chat_id,
|
||||||
@ -4353,7 +4352,7 @@ class CliClient final : public Actor {
|
|||||||
}
|
}
|
||||||
BufferSlice block(it->part_size);
|
BufferSlice block(it->part_size);
|
||||||
FileFd::open(it->source, FileFd::Flags::Read).move_as_ok().pread(block.as_slice(), it->local_size).ensure();
|
FileFd::open(it->source, FileFd::Flags::Read).move_as_ok().pread(block.as_slice(), it->local_size).ensure();
|
||||||
if (Random::fast(0, 1) == 0) {
|
if (Random::fast_bool()) {
|
||||||
auto open_flags = FileFd::Flags::Write | (it->local_size ? 0 : FileFd::Flags::Truncate | FileFd::Flags::Create);
|
auto open_flags = FileFd::Flags::Write | (it->local_size ? 0 : FileFd::Flags::Truncate | FileFd::Flags::Create);
|
||||||
FileFd::open(it->destination, open_flags).move_as_ok().pwrite(block.as_slice(), it->local_size).ensure();
|
FileFd::open(it->destination, open_flags).move_as_ok().pwrite(block.as_slice(), it->local_size).ensure();
|
||||||
} else {
|
} else {
|
||||||
|
@ -13,22 +13,23 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void *td_create() {
|
EMSCRIPTEN_KEEPALIVE double td_emscripten_create() {
|
||||||
return td_json_client_create();
|
return td_create_client();
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE void td_send(void *client, const char *query) {
|
|
||||||
td_json_client_send(client, query);
|
EMSCRIPTEN_KEEPALIVE void td_emscripten_send(double client_id, const char *query) {
|
||||||
|
td_send(static_cast<int>(client_id), query);
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE const char *td_receive(void *client) {
|
|
||||||
return td_json_client_receive(client, 0);
|
EMSCRIPTEN_KEEPALIVE const char *td_emscripten_receive() {
|
||||||
|
return td_receive(0);
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE const char *td_execute(void *client, const char *query) {
|
|
||||||
return td_json_client_execute(client, query);
|
EMSCRIPTEN_KEEPALIVE const char *td_emscripten_execute(const char *query) {
|
||||||
|
return td_execute(query);
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE void td_destroy(void *client) {
|
|
||||||
td_json_client_destroy(client);
|
EMSCRIPTEN_KEEPALIVE double td_emscripten_get_timeout() {
|
||||||
}
|
|
||||||
EMSCRIPTEN_KEEPALIVE double td_get_timeout() {
|
|
||||||
return td::ConcurrentScheduler::emscripten_get_main_timeout();
|
return td::ConcurrentScheduler::emscripten_get_main_timeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ class MainQueryActor final : public Actor {
|
|||||||
void wakeup() override {
|
void wakeup() override {
|
||||||
int cnt = 100000;
|
int cnt = 100000;
|
||||||
while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) {
|
while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) {
|
||||||
if (Random::fast(0, 1)) {
|
if (Random::fast_bool()) {
|
||||||
send_closure(rand_elem(actors_), &QueryActor::query, create_query());
|
send_closure(rand_elem(actors_), &QueryActor::query, create_query());
|
||||||
} else {
|
} else {
|
||||||
send_closure_later(rand_elem(actors_), &QueryActor::query, create_query());
|
send_closure_later(rand_elem(actors_), &QueryActor::query, create_query());
|
||||||
@ -306,7 +306,7 @@ class SimpleActor final : public Actor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
q_++;
|
q_++;
|
||||||
p_ = Random::fast(0, 1) ? 1 : 10000;
|
p_ = Random::fast_bool() ? 1 : 10000;
|
||||||
auto future = Random::fast(0, 3) == 0 ? send_promise<ActorSendType::Immediate>(worker_, &Worker::query, q_, p_)
|
auto future = Random::fast(0, 3) == 0 ? send_promise<ActorSendType::Immediate>(worker_, &Worker::query, q_, p_)
|
||||||
: send_promise<ActorSendType::Later>(worker_, &Worker::query, q_, p_);
|
: send_promise<ActorSendType::Later>(worker_, &Worker::query, q_, p_);
|
||||||
if (future.is_ready()) {
|
if (future.is_ready()) {
|
||||||
|
@ -148,6 +148,10 @@ double Random::fast(double min, double max) {
|
|||||||
return min + fast_uint32() * 1.0 / std::numeric_limits<uint32>::max() * (max - min);
|
return min + fast_uint32() * 1.0 / std::numeric_limits<uint32>::max() * (max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Random::fast_bool() {
|
||||||
|
return (fast_uint32() & 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
Random::Xorshift128plus::Xorshift128plus(uint64 seed) {
|
Random::Xorshift128plus::Xorshift128plus(uint64 seed) {
|
||||||
auto next = [&] {
|
auto next = [&] {
|
||||||
// splitmix64
|
// splitmix64
|
||||||
|
@ -35,6 +35,7 @@ class Random {
|
|||||||
// distribution is not uniform, min and max are included
|
// distribution is not uniform, min and max are included
|
||||||
static int fast(int min, int max);
|
static int fast(int min, int max);
|
||||||
static double fast(double min, double max);
|
static double fast(double min, double max);
|
||||||
|
static bool fast_bool();
|
||||||
|
|
||||||
class Fast {
|
class Fast {
|
||||||
public:
|
public:
|
||||||
|
@ -34,7 +34,7 @@ vector<string> rand_split(Slice str) {
|
|||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while (pos < str.size()) {
|
while (pos < str.size()) {
|
||||||
size_t len;
|
size_t len;
|
||||||
if (Random::fast(0, 1) == 1) {
|
if (Random::fast_bool()) {
|
||||||
len = Random::fast(1, 10);
|
len = Random::fast(1, 10);
|
||||||
} else {
|
} else {
|
||||||
len = Random::fast(100, 200);
|
len = Random::fast(100, 200);
|
||||||
|
@ -42,7 +42,7 @@ TEST(EpochBaseMemoryReclamation, stress) {
|
|||||||
locker.retire();
|
locker.retire();
|
||||||
}
|
}
|
||||||
if (td::Random::fast(0, 5) == 0) {
|
if (td::Random::fast(0, 5) == 0) {
|
||||||
std::string *new_str = new std::string(td::Random::fast(0, 1) == 0 ? "one" : "twotwo");
|
std::string *new_str = new std::string(td::Random::fast_bool() ? "one" : "twotwo");
|
||||||
if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) {
|
if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) {
|
||||||
locker.retire(str);
|
locker.retire(str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,7 +36,7 @@ TEST(HazardPointers, stress) {
|
|||||||
}
|
}
|
||||||
holder.clear();
|
holder.clear();
|
||||||
if (td::Random::fast(0, 5) == 0) {
|
if (td::Random::fast(0, 5) == 0) {
|
||||||
std::string *new_str = new std::string(td::Random::fast(0, 1) == 0 ? "one" : "twotwo");
|
std::string *new_str = new std::string(td::Random::fast_bool() ? "one" : "twotwo");
|
||||||
if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) {
|
if (node.name_.compare_exchange_strong(str, new_str, std::memory_order_acq_rel)) {
|
||||||
hazard_pointers.retire(thread_id, str);
|
hazard_pointers.retire(thread_id, str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -18,7 +18,7 @@ TEST(OrderedEventsProcessor, random) {
|
|||||||
int offset = 1000000;
|
int offset = 1000000;
|
||||||
std::vector<std::pair<int, int>> v;
|
std::vector<std::pair<int, int>> v;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
auto shift = td::Random::fast(0, 1) ? td::Random::fast(0, d) : td::Random::fast(0, 1) * d;
|
auto shift = td::Random::fast_bool() ? td::Random::fast(0, d) : td::Random::fast(0, 1) * d;
|
||||||
v.push_back({i + shift, i + offset});
|
v.push_back({i + shift, i + offset});
|
||||||
}
|
}
|
||||||
std::sort(v.begin(), v.end());
|
std::sort(v.begin(), v.end());
|
||||||
|
@ -37,16 +37,16 @@ TEST(Buffer, buffer_builder) {
|
|||||||
int r = l;
|
int r = l;
|
||||||
BufferBuilder builder(splitted_str[l], 123, 1000);
|
BufferBuilder builder(splitted_str[l], 123, 1000);
|
||||||
while (l != 0 || r != static_cast<int32>(splitted_str.size()) - 1) {
|
while (l != 0 || r != static_cast<int32>(splitted_str.size()) - 1) {
|
||||||
if (l == 0 || (Random::fast(0, 1) == 1 && r != static_cast<int32>(splitted_str.size() - 1))) {
|
if (l == 0 || (Random::fast_bool() && r != static_cast<int32>(splitted_str.size() - 1))) {
|
||||||
r++;
|
r++;
|
||||||
if (Random::fast(0, 1) == 1) {
|
if (Random::fast_bool()) {
|
||||||
builder.append(splitted_str[r]);
|
builder.append(splitted_str[r]);
|
||||||
} else {
|
} else {
|
||||||
builder.append(BufferSlice(splitted_str[r]));
|
builder.append(BufferSlice(splitted_str[r]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
l--;
|
l--;
|
||||||
if (Random::fast(0, 1) == 1) {
|
if (Random::fast_bool()) {
|
||||||
builder.prepend(splitted_str[l]);
|
builder.prepend(splitted_str[l]);
|
||||||
} else {
|
} else {
|
||||||
builder.prepend(BufferSlice(splitted_str[l]));
|
builder.prepend(BufferSlice(splitted_str[l]));
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
//
|
//
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
|
||||||
namespace td {
|
|
||||||
|
|
||||||
static const char thumbnail_arr[] =
|
static const char thumbnail_arr[] =
|
||||||
"_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAICAgICAQICAgIDAgIDAwYEAwMDAwcFBQQGCAcJCAgHCAgJCg0LCQoMCggICw8LDA0ODg8OCQsQERAOEQ"
|
"_9j_4AAQSkZJRgABAQEASABIAAD_2wBDAAICAgICAQICAgIDAgIDAwYEAwMDAwcFBQQGCAcJCAgHCAgJCg0LCQoMCggICw8LDA0ODg8OCQsQERAOEQ"
|
||||||
"0ODg7_2wBDAQIDAwMDAwcEBAcOCQgJDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg7_wAARCAAyADIDASIA"
|
"0ODg7_2wBDAQIDAwMDAwcEBAcOCQgJDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg7_wAARCAAyADIDASIA"
|
||||||
@ -157,5 +155,3 @@ static const char sqlite_sample_db_arr[] =
|
|||||||
|
|
||||||
const char *sqlite_sample_db = sqlite_sample_db_arr;
|
const char *sqlite_sample_db = sqlite_sample_db_arr;
|
||||||
const size_t sqlite_sample_db_size = sizeof(sqlite_sample_db_arr) - 1;
|
const size_t sqlite_sample_db_size = sizeof(sqlite_sample_db_arr) - 1;
|
||||||
|
|
||||||
} // namespace td
|
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
|
|
||||||
namespace td {
|
|
||||||
|
|
||||||
extern const char *thumbnail;
|
extern const char *thumbnail;
|
||||||
extern const size_t thumbnail_size;
|
extern const size_t thumbnail_size;
|
||||||
|
|
||||||
@ -18,5 +16,3 @@ extern const size_t gzip_bomb_size;
|
|||||||
|
|
||||||
extern const char *sqlite_sample_db;
|
extern const char *sqlite_sample_db;
|
||||||
extern const size_t sqlite_sample_db_size;
|
extern const size_t sqlite_sample_db_size;
|
||||||
|
|
||||||
} // namespace td
|
|
||||||
|
@ -99,8 +99,8 @@ static string make_http_query(string content, bool is_chunked, bool is_gzip, dou
|
|||||||
}
|
}
|
||||||
|
|
||||||
static string rand_http_query(string content) {
|
static string rand_http_query(string content) {
|
||||||
bool is_chunked = Random::fast(0, 1) == 0;
|
bool is_chunked = Random::fast_bool();
|
||||||
bool is_gzip = Random::fast(0, 1) == 0;
|
bool is_gzip = Random::fast_bool();
|
||||||
return make_http_query(std::move(content), is_chunked, is_gzip);
|
return make_http_query(std::move(content), is_chunked, is_gzip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,7 +964,7 @@ TEST(MessageEntities, fix_formatted_text) {
|
|||||||
{td::MessageEntity::Type::Italic, 2, 11}});
|
{td::MessageEntity::Type::Italic, 2, 11}});
|
||||||
|
|
||||||
for (size_t test_n = 0; test_n < 100000; test_n++) {
|
for (size_t test_n = 0; test_n < 100000; test_n++) {
|
||||||
bool is_url = td::Random::fast(0, 1) == 1;
|
bool is_url = td::Random::fast_bool();
|
||||||
td::int32 url_offset = 0;
|
td::int32 url_offset = 0;
|
||||||
td::int32 url_end = 0;
|
td::int32 url_end = 0;
|
||||||
if (is_url) {
|
if (is_url) {
|
||||||
|
@ -786,7 +786,7 @@ class Master : public Actor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void send_net_query(NetQueryPtr query, ActorShared<NetQueryCallback> callback, bool ordered) {
|
void send_net_query(NetQueryPtr query, ActorShared<NetQueryCallback> callback, bool ordered) {
|
||||||
if (can_fail(query) && Random::fast(0, 1) == 0) {
|
if (can_fail(query) && Random::fast_bool()) {
|
||||||
LOG(INFO) << "Fail query " << query;
|
LOG(INFO) << "Fail query " << query;
|
||||||
auto resend_promise =
|
auto resend_promise =
|
||||||
PromiseCreator::lambda([id = actor_shared(this, get_link_token()), callback_actor = callback.get(),
|
PromiseCreator::lambda([id = actor_shared(this, get_link_token()), callback_actor = callback.get(),
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user