Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2020-12-25 20:29:10 +01:00
commit 3817c4f634
43 changed files with 433 additions and 109 deletions

View File

@ -499,6 +499,7 @@ set(TDLIB_SOURCE
td/telegram/FullMessageId.h
td/telegram/Game.h
td/telegram/Global.h
td/telegram/GroupCallId.h
td/telegram/GroupCallManager.h
td/telegram/GroupCallParticipant.h
td/telegram/HashtagHints.h

View File

@ -28,6 +28,7 @@
static constexpr int DATA_SIZE = 8 << 10;
static constexpr int SHORT_DATA_SIZE = 64;
#if OPENSSL_VERSION_NUMBER <= 0x10100000L
class SHA1Bench : public td::Benchmark {
public:
alignas(64) unsigned char data[DATA_SIZE];
@ -50,6 +51,7 @@ class SHA1Bench : public td::Benchmark {
}
}
};
#endif
class AesEcbBench : public td::Benchmark {
public:
@ -433,7 +435,9 @@ int main() {
td::bench(SslRandBench());
#endif
td::bench(SslRandBufBench());
#if OPENSSL_VERSION_NUMBER <= 0x10100000L
td::bench(SHA1Bench());
#endif
td::bench(Crc32Bench());
td::bench(Crc64Bench());
}

View File

@ -3229,7 +3229,7 @@ messageStatistics message_interaction_graph:StatisticalGraph = MessageStatistics
point x:double y:double = Point;
//@class VectorPathCommand @description Reperesents a vector path command
//@class VectorPathCommand @description Represents a vector path command
//@description A straight line to a given point @end_point The end point of the straight line
vectorPathCommandLine end_point:point = VectorPathCommand;
@ -3892,12 +3892,12 @@ getMessageLinkInfo url:string = MessageLinkInfo;
//@reply_markup Markup for replying to the message; for bots only @input_message_content The content of the message to be sent
sendMessage chat_id:int53 message_thread_id:int53 reply_to_message_id:int53 options:messageSendOptions reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
//@description Sends messages grouped together into an album. Currently only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages
//@description Sends 2-10 messages grouped together into an album. Currently only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages
//@chat_id Target chat
//@message_thread_id If not 0, a message thread identifier in which the messages will be sent
//@reply_to_message_id Identifier of a message to reply to or 0
//@options Options to be used to send the messages
//@input_message_contents Contents of messages to be sent
//@input_message_contents Contents of messages to be sent. At most 10 messages can be added to an album
sendMessageAlbum chat_id:int53 message_thread_id:int53 reply_to_message_id:int53 options:messageSendOptions input_message_contents:vector<InputMessageContent> = Messages;
//@description Invites a bot to a chat (if it is not yet a member) and sends it the /start command. Bots can't be invited to a private chat other than the chat with the bot. Bots can't be invited to channels (although they can be added as admins) and secret chats. Returns the sent message
@ -3914,7 +3914,9 @@ sendBotStartMessage bot_user_id:int32 chat_id:int53 parameter:string = Message;
sendInlineQueryResultMessage chat_id:int53 message_thread_id:int53 reply_to_message_id:int53 options:messageSendOptions query_id:int64 result_id:string hide_via_bot:Bool = Message;
//@description Forwards previously sent messages. Returns the forwarded messages in the same order as the message identifiers passed in message_ids. If a message can't be forwarded, null will be returned instead of the message
//@chat_id Identifier of the chat to which to forward messages @from_chat_id Identifier of the chat from which to forward messages @message_ids Identifiers of the messages to forward. Message identifiers must be in a strictly increasing order
//@chat_id Identifier of the chat to which to forward messages
//@from_chat_id Identifier of the chat from which to forward messages
//@message_ids Identifiers of the messages to forward. Message identifiers must be in a strictly increasing order. At most 100 messages can be forwarded simultaneously
//@options Options to be used to send the messages
//@send_copy True, if content of the messages needs to be copied without links to the original messages. Always true if the messages are forwarded to a secret chat
//@remove_caption True, if media caption of message copies needs to be removed. Ignored if send_copy is false

View File

@ -20,8 +20,11 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/opensslv.h>
#include <openssl/pem.h>
#if OPENSSL_VERSION_NUMBER < 0x30000000L
#include <openssl/rsa.h>
#endif
namespace td {
@ -44,25 +47,55 @@ Result<RSA> RSA::from_pem_public_key(Slice pem) {
BIO_free(bio);
};
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY *rsa = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
#else
auto rsa = PEM_read_bio_RSAPublicKey(bio, nullptr, nullptr, nullptr);
#endif
if (rsa == nullptr) {
return Status::Error("Error while reading rsa pubkey");
return Status::Error("Error while reading RSA public key");
}
SCOPE_EXIT {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY_free(rsa);
#else
RSA_free(rsa);
#endif
};
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (!EVP_PKEY_is_a(rsa, "RSA")) {
return Status::Error("Key is not an RSA key");
}
if (EVP_PKEY_size(rsa) != 256) {
return Status::Error("EVP_PKEY_size != 256");
}
#else
if (RSA_size(rsa) != 256) {
return Status::Error("RSA_size != 256");
}
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
BIGNUM *n_num = nullptr;
BIGNUM *e_num = nullptr;
int res = EVP_PKEY_get_bn_param(rsa, "n", &n_num);
CHECK(res == 1 && n_num != nullptr);
res = EVP_PKEY_get_bn_param(rsa, "e", &e_num);
CHECK(res == 1 && e_num != nullptr);
auto n = static_cast<void *>(n_num);
auto e = static_cast<void *>(e_num);
#else
const BIGNUM *n_num;
const BIGNUM *e_num;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
RSA_get0_key(rsa, &n_num, &e_num, nullptr);
#else
n_num = rsa->n;
e_num = rsa->e;
#else
RSA_get0_key(rsa, &n_num, &e_num, nullptr);
#endif
auto n = static_cast<void *>(BN_dup(n_num));
@ -70,6 +103,7 @@ Result<RSA> RSA::from_pem_public_key(Slice pem) {
if (n == nullptr || e == nullptr) {
return Status::Error("Cannot dup BIGNUM");
}
#endif
return RSA(BigNum::from_raw(n), BigNum::from_raw(e));
}
@ -104,6 +138,7 @@ size_t RSA::encrypt(unsigned char *from, size_t from_len, size_t max_from_len, u
CHECK(chunks * 256 <= to_len);
Random::secure_bytes(from + from_len, pad);
size_t result = chunks * 256;
BigNumContext ctx;
BigNum y;
while (chunks-- > 0) {
@ -112,7 +147,7 @@ size_t RSA::encrypt(unsigned char *from, size_t from_len, size_t max_from_len, u
MutableSlice(to, 256).copy_from(y.to_binary(256));
to += 256;
}
return chunks * 256;
return result;
}
void RSA::decrypt_signature(Slice from, MutableSlice to) const {

View File

@ -19,7 +19,6 @@
#include "td/telegram/files/FileType.h"
#include "td/telegram/FolderId.h"
#include "td/telegram/Global.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/InputGroupCallId.h"
#include "td/telegram/logevent/LogEvent.h"

View File

@ -6,21 +6,25 @@
//
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/AccessRights.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/Td.h"
#include "td/telegram/UpdatesManager.h"
#include "td/actor/MultiPromise.h"
#include "td/utils/buffer.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/misc.h"
#include "td/utils/Random.h"
#include <limits>
#include <map>
#include <unordered_set>
#include <utility>

View File

@ -18,6 +18,8 @@
#include "td/actor/PromiseFuture.h"
#include "td/actor/Timeout.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/Status.h"
#include <unordered_map>

View File

@ -8,6 +8,8 @@
#include "td/telegram/ContactsManager.h"
#include "td/utils/logging.h"
namespace td {
GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {

View File

@ -6,9 +6,6 @@
//
#include "td/telegram/InputGroupCallId.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
namespace td {
InputGroupCallId::InputGroupCallId(const tl_object_ptr<telegram_api::inputGroupCall> &input_group_call)

View File

@ -844,26 +844,34 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation,
poll->was_saved = false;
}
if (result.is_ok()) {
td_->updates_manager_->on_get_updates(result.move_as_ok(), Promise<Unit>());
for (auto &promise : promises) {
promise.set_value(Unit());
}
td_->updates_manager_->on_get_updates(
result.move_as_ok(), PromiseCreator::lambda([actor_id = actor_id(this), poll_id,
promises = std::move(promises)](Result<Unit> &&result) mutable {
send_closure(actor_id, &PollManager::on_set_poll_answer_finished, poll_id, Unit(), std::move(promises));
}));
} else {
for (auto &promise : promises) {
promise.set_error(result.error().clone());
on_set_poll_answer_finished(poll_id, result.move_as_error(), std::move(promises));
}
}
void PollManager::on_set_poll_answer_finished(PollId poll_id, Result<Unit> &&result, vector<Promise<Unit>> &&promises) {
if (!G()->close_flag()) {
auto poll = get_poll(poll_id);
if (poll != nullptr && !poll->was_saved) {
// no updates was sent during updates processing, so send them
// poll wasn't changed, so there is no reason to actually save it
if (!(poll->is_closed && poll->is_updated_after_close)) {
LOG(INFO) << "Schedule updating of " << poll_id << " soon";
update_poll_timeout_.set_timeout_in(poll_id.get(), 0.0);
}
notify_on_poll_update(poll_id);
poll->was_saved = true;
}
}
if (poll != nullptr && !poll->was_saved) {
// no updates was sent during updates processing, so send them
// poll wasn't changed, so there is no reason to actually save it
if (!(poll->is_closed && poll->is_updated_after_close)) {
LOG(INFO) << "Schedule updating of " << poll_id << " soon";
update_poll_timeout_.set_timeout_in(poll_id.get(), 0.0);
}
notify_on_poll_update(poll_id);
poll->was_saved = true;
for (auto &promise : promises) {
promise.set_result(result.clone());
}
}

View File

@ -186,6 +186,8 @@ class PollManager : public Actor {
void on_set_poll_answer(PollId poll_id, uint64 generation, Result<tl_object_ptr<telegram_api::Updates>> &&result);
void on_set_poll_answer_finished(PollId poll_id, Result<Unit> &&result, vector<Promise<Unit>> &&promises);
void invalidate_poll_voters(const Poll *poll, PollId poll_id);
void invalidate_poll_option_voters(const Poll *poll, PollId poll_id, size_t option_index);

View File

@ -47,6 +47,8 @@
#include "td/utils/PathView.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"
@ -1503,7 +1505,7 @@ vector<td_api::object_ptr<td_api::closedVectorPath>> StickersManager::get_sticke
case 'm':
case 'M':
pos--;
// falltrough
// fallthrough
case 'z':
case 'Z':
if (x != start_x || y != start_y) {

View File

@ -43,6 +43,7 @@
#include "td/telegram/FolderId.h"
#include "td/telegram/FullMessageId.h"
#include "td/telegram/Global.h"
#include "td/telegram/GroupCallId.h"
#include "td/telegram/GroupCallManager.h"
#include "td/telegram/HashtagHints.h"
#include "td/telegram/InlineQueriesManager.h"

View File

@ -1119,17 +1119,24 @@ void UpdatesManager::on_get_difference(tl_object_ptr<telegram_api::updates_Diffe
seq_ = difference->seq_;
if (!pending_seq_updates_.empty()) {
LOG(WARNING) << "Drop " << pending_seq_updates_.size() << " pending seq updates after receive empty difference";
for (auto &pending_update : pending_seq_updates_) {
auto pending_seq_updates = std::move(pending_seq_updates_);
pending_seq_updates_.clear();
for (auto &pending_update : pending_seq_updates) {
pending_update.second.promise.set_value(Unit());
}
pending_seq_updates_.clear();
}
if (!pending_qts_updates_.empty()) {
LOG(WARNING) << "Drop " << pending_qts_updates_.size() << " pending qts updates after receive empty difference";
for (auto &pending_update : pending_qts_updates_) {
pending_update.second.promise.set_value(Unit());
}
auto pending_qts_updates = std::move(pending_qts_updates_);
pending_qts_updates_.clear();
for (auto &pending_update : pending_qts_updates) {
auto promises = std::move(pending_update.second.promises);
for (auto &promise : promises) {
promise.set_value(Unit());
}
}
}
break;
}
@ -1258,7 +1265,7 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
return promise.set_value(Unit());
}
if (running_get_difference_) {
if (running_get_difference_ /*|| string(source) != string("postponed updates")*/) {
LOG(INFO) << "Postpone " << updates.size() << " updates [" << seq_begin << ", " << seq_end
<< "] with date = " << date << " from " << source;
postponed_updates_.emplace(seq_begin,
@ -1446,10 +1453,8 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
LOG(INFO) << "Gap in seq has found. Receive " << updates.size() << " updates [" << seq_begin << ", " << seq_end
<< "] from " << source << ", but seq = " << seq_;
if (pending_seq_updates_.find(seq_begin) != pending_seq_updates_.end()) {
LOG(WARNING) << "Already have pending updates with seq = " << seq_begin << ", but receive it again from " << source;
pending_seq_updates_.find(seq_begin)->second.promise.set_value(Unit()); // TODO
}
LOG_IF(WARNING, pending_seq_updates_.find(seq_begin) != pending_seq_updates_.end())
<< "Already have pending updates with seq = " << seq_begin << ", but receive it again from " << source;
pending_seq_updates_.emplace(seq_begin,
PendingUpdates(seq_begin, seq_end, date, std::move(updates), mpas.get_promise()));
@ -1492,10 +1497,9 @@ void UpdatesManager::add_pending_qts_update(tl_object_ptr<telegram_api::Update>
auto &pending_update = pending_qts_updates_[qts];
if (pending_update.update != nullptr) {
LOG(WARNING) << "Receive duplicate update with qts = " << qts;
pending_update.promise.set_value(Unit()); // TODO
}
pending_update.update = std::move(update);
pending_update.promise = std::move(promise);
pending_update.promises.push_back(std::move(promise));
return;
}
@ -1620,6 +1624,7 @@ void UpdatesManager::process_pending_seq_updates() {
LOG_IF(ERROR, update_it->second.seq_end > seq_)
<< "Strange updates coming with seq_begin = " << seq_begin << ", seq_end = " << update_it->second.seq_end
<< ", but seq = " << seq_;
update_it->second.promise.set_value(Unit());
}
pending_seq_updates_.erase(update_it);
}
@ -1643,8 +1648,15 @@ void UpdatesManager::process_pending_qts_updates() {
if (qts > get_qts() + 1) {
break;
}
auto promise = PromiseCreator::lambda([promises = std::move(update_it->second.promises)](Unit) mutable {
for (auto &promise : promises) {
promise.set_value(Unit());
}
});
if (qts == get_qts() + 1) {
process_qts_update(std::move(update_it->second.update), qts, std::move(update_it->second.promise));
process_qts_update(std::move(update_it->second.update), qts, std::move(promise));
} else {
promise.set_value(Unit());
}
pending_qts_updates_.erase(update_it);
}

View File

@ -103,7 +103,7 @@ class UpdatesManager : public Actor {
class PendingQtsUpdate {
public:
tl_object_ptr<telegram_api::Update> update;
Promise<Unit> promise;
vector<Promise<Unit>> promises;
};
Td *td_;

View File

@ -9,7 +9,7 @@
#include "td/telegram/Global.h"
#include "td/telegram/TdDb.h"
#include "tddb/td/db/binlog/BinlogHelper.h"
#include "td/db/binlog/BinlogHelper.h"
#include "td/utils/logging.h"
#include "td/utils/Status.h"

View File

@ -9,6 +9,7 @@
#include "td/utils/ExitGuard.h"
#include "td/utils/MpscPollableQueue.h"
#include "td/utils/port/thread_local.h"
#include "td/utils/ScopeGuard.h"
#include <memory>
@ -137,10 +138,12 @@ void ConcurrentScheduler::finish() {
#endif
if (ExitGuard::is_exited()) {
#if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED
// prevent closing of schedulers from already killed by OS threads
for (auto &thread : threads_) {
thread.detach();
}
#endif
#if TD_PORT_WINDOWS
iocp_->interrupt_loop();

View File

@ -12,6 +12,7 @@
#include "td/utils/Closure.h"
#include "td/utils/common.h"
#include "td/utils/invoke.h" // for tuple_for_each
#include "td/utils/MovableValue.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Status.h"

View File

@ -4,7 +4,7 @@
// 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 "tl_config.h"
#include "td/tl/tl_config.h"
#include <cassert>
#include <cstdio>

View File

@ -6,8 +6,8 @@
//
#pragma once
#include "tl_core.h"
#include "tl_simple_parser.h"
#include "td/tl/tl_core.h"
#include "td/tl/tl_simple_parser.h"
#include <cstddef>
#include <cstdint>

View File

@ -4,7 +4,7 @@
// 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 "tl_core.h"
#include "td/tl/tl_core.h"
#include <cassert>

View File

@ -4,7 +4,7 @@
// 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 "tl_file_outputer.h"
#include "td/tl/tl_file_outputer.h"
#include <cassert>

View File

@ -6,7 +6,7 @@
//
#pragma once
#include "tl_outputer.h"
#include "td/tl/tl_outputer.h"
#include <cstdio>
#include <string>

View File

@ -4,7 +4,7 @@
// 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 "tl_file_utils.h"
#include "td/tl/tl_file_utils.h"
#include <cstdio>
#include <cstdlib>

View File

@ -4,14 +4,14 @@
// 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 "tl_generate.h"
#include "td/tl/tl_generate.h"
#include "tl_config.h"
#include "tl_core.h"
#include "tl_file_utils.h"
#include "tl_outputer.h"
#include "tl_string_outputer.h"
#include "tl_writer.h"
#include "td/tl/tl_config.h"
#include "td/tl/tl_core.h"
#include "td/tl/tl_file_utils.h"
#include "td/tl/tl_outputer.h"
#include "td/tl/tl_string_outputer.h"
#include "td/tl/tl_writer.h"
#include <cassert>
#include <cstdint>

View File

@ -6,9 +6,9 @@
//
#pragma once
#include "tl_config.h"
#include "tl_outputer.h"
#include "tl_writer.h"
#include "td/tl/tl_config.h"
#include "td/tl/tl_outputer.h"
#include "td/tl/tl_writer.h"
#include <string>

View File

@ -4,7 +4,7 @@
// 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 "tl_outputer.h"
#include "td/tl/tl_outputer.h"
namespace td {
namespace tl {

View File

@ -4,7 +4,7 @@
// 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 "tl_string_outputer.h"
#include "td/tl/tl_string_outputer.h"
namespace td {
namespace tl {

View File

@ -6,7 +6,7 @@
//
#pragma once
#include "tl_outputer.h"
#include "td/tl/tl_outputer.h"
#include <string>

View File

@ -4,9 +4,9 @@
// 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 "tl_writer.h"
#include "td/tl/tl_writer.h"
#include "tl_core.h"
#include "td/tl/tl_core.h"
#include <cassert>
#include <cstdio>

View File

@ -6,7 +6,7 @@
//
#pragma once
#include "tl_core.h"
#include "td/tl/tl_core.h"
#include <cstdint>
#include <string>

View File

@ -123,6 +123,7 @@ set(TDUTILS_SOURCE
td/utils/port/EventFd.h
td/utils/port/EventFdBase.h
td/utils/port/FileFd.h
td/utils/port/FromApp.h
td/utils/port/IPAddress.h
td/utils/port/IoSlice.h
td/utils/port/MemoryMapping.h

View File

@ -147,7 +147,12 @@ bool BigNum::is_bit_set(int num) const {
}
bool BigNum::is_prime(BigNumContext &context) const {
int result = BN_is_prime_ex(impl_->big_num, BN_prime_checks, context.impl_->big_num_context, nullptr);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int result = BN_check_prime(impl_->big_num, context.impl_->big_num_context, nullptr);
#else
int result =
BN_is_prime_ex(impl_->big_num, get_num_bits() > 2048 ? 128 : 64, context.impl_->big_num_context, nullptr);
#endif
LOG_IF(FATAL, result == -1);
return result == 1;
}

View File

@ -28,11 +28,17 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/opensslv.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/params.h>
#endif
#if TD_HAVE_ZLIB
#include <zlib.h>
#endif
@ -674,21 +680,47 @@ void AesCtrState::decrypt(Slice from, MutableSlice to) {
encrypt(from, to);
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) {
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
LOG_IF(FATAL, ctx == nullptr);
int res = EVP_DigestInit_ex(ctx, evp_md, nullptr);
LOG_IF(FATAL, res != 1);
res = EVP_DigestUpdate(ctx, data.ubegin(), data.size());
LOG_IF(FATAL, res != 1);
res = EVP_DigestFinal_ex(ctx, output.ubegin(), nullptr);
LOG_IF(FATAL, res != 1);
EVP_MD_CTX_free(ctx);
}
#endif
void sha1(Slice data, unsigned char output[20]) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
make_digest(data, MutableSlice(output, 20), EVP_sha1());
#else
auto result = SHA1(data.ubegin(), data.size(), output);
CHECK(result == output);
#endif
}
void sha256(Slice data, MutableSlice output) {
CHECK(output.size() >= 32);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
make_digest(data, output, EVP_sha256());
#else
auto result = SHA256(data.ubegin(), data.size(), output.ubegin());
CHECK(result == output.ubegin());
#endif
}
void sha512(Slice data, MutableSlice output) {
CHECK(output.size() >= 64);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
make_digest(data, output, EVP_sha512());
#else
auto result = SHA512(data.ubegin(), data.size(), output.ubegin());
CHECK(result == output.ubegin());
#endif
}
string sha256(Slice data) {
@ -705,7 +737,27 @@ string sha512(Slice data) {
class Sha256State::Impl {
public:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MD_CTX *ctx_;
Impl() {
ctx_ = EVP_MD_CTX_new();
LOG_IF(FATAL, ctx_ == nullptr);
}
~Impl() {
CHECK(ctx_ != nullptr);
EVP_MD_CTX_free(ctx_);
}
#else
SHA256_CTX ctx_;
Impl() = default;
~Impl() = default;
#endif
Impl(const Impl &from) = delete;
Impl &operator=(const Impl &from) = delete;
Impl(Impl &&from) = delete;
Impl &operator=(Impl &&from) = delete;
};
Sha256State::Sha256State() = default;
@ -737,7 +789,11 @@ void Sha256State::init() {
impl_ = make_unique<Sha256State::Impl>();
}
CHECK(!is_inited_);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int err = EVP_DigestInit_ex(impl_->ctx_, EVP_sha256(), nullptr);
#else
int err = SHA256_Init(&impl_->ctx_);
#endif
LOG_IF(FATAL, err != 1);
is_inited_ = true;
}
@ -745,7 +801,11 @@ void Sha256State::init() {
void Sha256State::feed(Slice data) {
CHECK(impl_);
CHECK(is_inited_);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int err = EVP_DigestUpdate(impl_->ctx_, data.ubegin(), data.size());
#else
int err = SHA256_Update(&impl_->ctx_, data.ubegin(), data.size());
#endif
LOG_IF(FATAL, err != 1);
}
@ -753,7 +813,11 @@ void Sha256State::extract(MutableSlice output, bool destroy) {
CHECK(output.size() >= 32);
CHECK(impl_);
CHECK(is_inited_);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int err = EVP_DigestFinal_ex(impl_->ctx_, output.ubegin(), nullptr);
#else
int err = SHA256_Final(output.ubegin(), &impl_->ctx_);
#endif
LOG_IF(FATAL, err != 1);
is_inited_ = false;
if (destroy) {
@ -762,9 +826,13 @@ void Sha256State::extract(MutableSlice output, bool destroy) {
}
void md5(Slice input, MutableSlice output) {
CHECK(output.size() >= MD5_DIGEST_LENGTH);
CHECK(output.size() >= 16);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
make_digest(input, output, EVP_md5());
#else
auto result = MD5(input.ubegin(), input.size(), output.ubegin());
CHECK(result == output.ubegin());
#endif
}
static void pbkdf2_impl(Slice password, Slice salt, int iteration_count, MutableSlice dest, const EVP_MD *evp_md) {
@ -812,22 +880,58 @@ void pbkdf2_sha512(Slice password, Slice salt, int iteration_count, MutableSlice
pbkdf2_impl(password, salt, iteration_count, dest, EVP_sha512());
}
void hmac_sha256(Slice key, Slice message, MutableSlice dest) {
CHECK(dest.size() == 256 / 8);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static void hmac_impl(const char *digest, Slice key, Slice message, MutableSlice dest) {
EVP_MAC *hmac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
LOG_IF(FATAL, hmac == nullptr);
EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(hmac);
LOG_IF(FATAL, ctx == nullptr);
OSSL_PARAM params[3];
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, const_cast<char *>(digest), 0);
params[1] =
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, const_cast<unsigned char *>(key.ubegin()), key.size());
params[2] = OSSL_PARAM_construct_end();
int res = EVP_MAC_CTX_set_params(ctx, params);
LOG_IF(FATAL, res != 1);
res = EVP_MAC_init(ctx);
LOG_IF(FATAL, res != 1);
res = EVP_MAC_update(ctx, message.ubegin(), message.size());
LOG_IF(FATAL, res != 1);
res = EVP_MAC_final(ctx, dest.ubegin(), nullptr, dest.size());
LOG_IF(FATAL, res != 1);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(hmac);
}
#else
static void hmac_impl(const EVP_MD *evp_md, Slice key, Slice message, MutableSlice dest) {
unsigned int len = 0;
auto result = HMAC(EVP_sha256(), key.ubegin(), narrow_cast<int>(key.size()), message.ubegin(),
auto result = HMAC(evp_md, key.ubegin(), narrow_cast<int>(key.size()), message.ubegin(),
narrow_cast<int>(message.size()), dest.ubegin(), &len);
CHECK(result == dest.ubegin());
CHECK(len == dest.size());
}
#endif
void hmac_sha256(Slice key, Slice message, MutableSlice dest) {
CHECK(dest.size() == 256 / 8);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
hmac_impl("SHA256", key, message, dest);
#else
hmac_impl(EVP_sha256(), key, message, dest);
#endif
}
void hmac_sha512(Slice key, Slice message, MutableSlice dest) {
CHECK(dest.size() == 512 / 8);
unsigned int len = 0;
auto result = HMAC(EVP_sha512(), key.ubegin(), narrow_cast<int>(key.size()), message.ubegin(),
narrow_cast<int>(message.size()), dest.ubegin(), &len);
CHECK(result == dest.ubegin());
CHECK(len == dest.size());
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
hmac_impl("SHA512", key, message, dest);
#else
hmac_impl(EVP_sha512(), key, message, dest);
#endif
}
static int get_evp_pkey_type(EVP_PKEY *pkey) {

View File

@ -204,19 +204,19 @@ class DefaultLog : public LogInterface {
#elif TD_TIZEN
switch (log_level) {
case VERBOSITY_NAME(FATAL):
dlog_print(DLOG_ERROR, DLOG_TAG, slice.c_str());
dlog_print(DLOG_ERROR, DLOG_TAG, "%s", slice.c_str());
break;
case VERBOSITY_NAME(ERROR):
dlog_print(DLOG_ERROR, DLOG_TAG, slice.c_str());
dlog_print(DLOG_ERROR, DLOG_TAG, "%s", slice.c_str());
break;
case VERBOSITY_NAME(WARNING):
dlog_print(DLOG_WARN, DLOG_TAG, slice.c_str());
dlog_print(DLOG_WARN, DLOG_TAG, "%s", slice.c_str());
break;
case VERBOSITY_NAME(INFO):
dlog_print(DLOG_INFO, DLOG_TAG, slice.c_str());
dlog_print(DLOG_INFO, DLOG_TAG, "%s", slice.c_str());
break;
default:
dlog_print(DLOG_DEBUG, DLOG_TAG, slice.c_str());
dlog_print(DLOG_DEBUG, DLOG_TAG, "%s", slice.c_str());
break;
}
#elif TD_EMSCRIPTEN

View File

@ -7,6 +7,7 @@
#include "td/utils/port/FileFd.h"
#if TD_PORT_WINDOWS
#include "td/utils/port/FromApp.h"
#include "td/utils/port/Stat.h"
#include "td/utils/port/wstring_convert.h"
#endif
@ -211,7 +212,8 @@ Result<FileFd> FileFd::open(CSlice filepath, int32 flags, int32 mode) {
extended_parameters.dwSize = sizeof(extended_parameters);
extended_parameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
extended_parameters.dwFileFlags = native_flags;
auto handle = CreateFile2(w_filepath.c_str(), desired_access, share_mode, creation_disposition, &extended_parameters);
auto handle = td::CreateFile2FromAppW(w_filepath.c_str(), desired_access, share_mode, creation_disposition,
&extended_parameters);
#endif
if (handle == INVALID_HANDLE_VALUE) {
return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags});

View File

@ -0,0 +1,90 @@
#pragma once
#include "td/utils/common.h"
#ifdef TD_PORT_WINDOWS
namespace td {
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
inline HMODULE GetKernelModule() {
static const auto kernel_module = []() -> HMODULE {
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(VirtualQuery, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) {
return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}
return nullptr;
}();
return kernel_module;
}
inline HMODULE LoadLibrary(LPCTSTR lpFileName) {
using pLoadLibrary = HMODULE(WINAPI *)(_In_ LPCTSTR);
static const auto proc_load_library =
reinterpret_cast<pLoadLibrary>(GetProcAddress(GetKernelModule(), "LoadLibraryW"));
return proc_load_library(lpFileName);
}
inline HMODULE GetFromAppModule() {
static const HMODULE from_app_module = LoadLibrary(L"api-ms-win-core-file-fromapp-l1-1-0.dll");
return from_app_module;
}
#endif
template <int num, class T>
T *get_from_app_function(const char *name, T *original_func) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
return original_func;
#else
static T *func = [name, original_func]() -> T * {
auto func_pointer = GetProcAddress(GetFromAppModule(), name);
if (func_pointer == nullptr) {
return original_func;
}
return reinterpret_cast<T *>(func_pointer);
}();
return func;
#endif
}
inline HANDLE CreateFile2FromAppW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,
_In_ DWORD dwCreationDisposition,
_In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) {
auto func = get_from_app_function<0>("CreateFile2FromAppW", &CreateFile2);
return func(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams);
}
inline BOOL CreateDirectoryFromAppW(_In_ LPCWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes) {
auto func = get_from_app_function<1>("CreateDirectoryFromAppW", &CreateDirectory);
return func(lpPathName, lpSecurityAttributes);
}
inline BOOL RemoveDirectoryFromAppW(_In_ LPCWSTR lpPathName) {
auto func = get_from_app_function<2>("RemoveDirectoryFromAppW", &RemoveDirectory);
return func(lpPathName);
}
inline BOOL DeleteFileFromAppW(_In_ LPCWSTR lpFileName) {
auto func = get_from_app_function<3>("DeleteFileFromAppW", &DeleteFile);
return func(lpFileName);
}
inline BOOL MoveFileExFromAppW(_In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) {
auto func = get_from_app_function<4>("MoveFileFromAppW", &MoveFileEx);
if (func != &MoveFileEx && (dwFlags & MOVEFILE_REPLACE_EXISTING) != 0) {
td::DeleteFileFromAppW(lpNewFileName);
}
return func(lpExistingFileName, lpNewFileName, dwFlags);
}
inline HANDLE FindFirstFileExFromAppW(_In_ LPCWSTR lpFileName, _In_ FINDEX_INFO_LEVELS fInfoLevelId,
_Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData,
_In_ FINDEX_SEARCH_OPS fSearchOp, _Reserved_ LPVOID lpSearchFilter,
_In_ DWORD dwAdditionalFlags) {
auto func = get_from_app_function<5>("FindFirstFileExFromAppW", &FindFirstFileEx);
return func(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
}
} // namespace td
#endif

View File

@ -127,11 +127,13 @@ class BufferedStdinImpl : public Iocp::Callback {
break;
}
writer_.confirm_append(r_size.ok());
if (iocp_ref_.post(0, this, nullptr)) {
inc_refcnt();
inc_refcnt();
if (!iocp_ref_.post(0, this, nullptr)) {
dec_refcnt();
}
}
if (!iocp_ref_.post(0, this, nullptr)) {
read_thread_.detach();
dec_refcnt();
}
}

View File

@ -14,6 +14,7 @@
#include "td/utils/ScopeGuard.h"
#if TD_PORT_WINDOWS
#include "td/utils/port/FromApp.h"
#include "td/utils/port/wstring_convert.h"
#include "td/utils/Random.h"
#endif
@ -390,7 +391,7 @@ Status WalkPath::do_run(CSlice path, const detail::WalkFunction &func) {
Status mkdir(CSlice dir, int32 mode) {
TRY_RESULT(wdir, to_wstring(dir));
auto status = CreateDirectoryW(wdir.c_str(), nullptr);
auto status = td::CreateDirectoryFromAppW(wdir.c_str(), nullptr);
if (status == 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
return OS_ERROR(PSLICE() << "Can't create directory \"" << dir << '"');
}
@ -400,7 +401,7 @@ Status mkdir(CSlice dir, int32 mode) {
Status rename(CSlice from, CSlice to) {
TRY_RESULT(wfrom, to_wstring(from));
TRY_RESULT(wto, to_wstring(to));
auto status = MoveFileExW(wfrom.c_str(), wto.c_str(), MOVEFILE_REPLACE_EXISTING);
auto status = td::MoveFileExFromAppW(wfrom.c_str(), wto.c_str(), MOVEFILE_REPLACE_EXISTING);
if (status == 0) {
return OS_ERROR(PSLICE() << "Can't rename \"" << from << "\" to \"" << to << '\"');
}
@ -443,7 +444,7 @@ Status chdir(CSlice dir) {
Status rmdir(CSlice dir) {
TRY_RESULT(wdir, to_wstring(dir));
int status = RemoveDirectoryW(wdir.c_str());
int status = td::RemoveDirectoryFromAppW(wdir.c_str());
if (!status) {
return OS_ERROR(PSLICE() << "Can't delete directory \"" << dir << '"');
}
@ -452,7 +453,7 @@ Status rmdir(CSlice dir) {
Status unlink(CSlice path) {
TRY_RESULT(wpath, to_wstring(path));
int status = DeleteFileW(wpath.c_str());
int status = td::DeleteFileFromAppW(wpath.c_str());
if (!status) {
return OS_ERROR(PSLICE() << "Can't unlink \"" << path << '"');
}
@ -549,7 +550,8 @@ static Result<bool> walk_path_dir(const std::wstring &dir_name,
const std::function<WalkPath::Action(CSlice name, WalkPath::Type type)> &func) {
std::wstring name = dir_name + L"\\*";
WIN32_FIND_DATA file_data;
auto handle = FindFirstFileExW(name.c_str(), FindExInfoStandard, &file_data, FindExSearchNameMatch, nullptr, 0);
auto handle =
td::FindFirstFileExFromAppW(name.c_str(), FindExInfoStandard, &file_data, FindExSearchNameMatch, nullptr, 0);
if (handle == INVALID_HANDLE_VALUE) {
return OS_ERROR(PSLICE() << "FindFirstFileEx" << tag("name", from_wstring(name).ok()));
}

View File

@ -303,6 +303,32 @@ TEST(Crypto, md5) {
ASSERT_STREQ(answers[i], td::base64_encode(output));
}
}
TEST(Crypto, hmac_sha256) {
td::vector<td::Slice> answers{
"t33rfT85UOe6N00BhsNwobE+f2TnW331HhdvQ4GdJp8=", "BQl5HF2jqhCz4JTqhAs+H364oxboh7QlluOMHuuRVh8=",
"NCCPuZBsAPBd/qr3SyeYE+e1RNgzkKJCS/+eXDBw8zU=", "mo3ahTkyLKfoQoYA0s7vRZULuH++vqwFJD0U5n9HHw0="};
for (std::size_t i = 0; i < strings.size(); i++) {
td::string output(32, '\0');
td::hmac_sha256("cucumber", strings[i], output);
ASSERT_STREQ(answers[i], td::base64_encode(output));
}
}
TEST(Crypto, hmac_sha512) {
td::vector<td::Slice> answers{
"o28hTN1m/TGlm/VYxDIzOdUE4wMpQzO8hVcTkiP2ezEJXtrOvCjRnl20aOV1S8axA5Te0TzIjfIoEAtpzamIsA==",
"32X3GslSz0HDznSrCNt++ePRcFVSUSD+tfOVannyxS+yLt/om11qILCE64RFTS8/B84gByMzC3FuAlfcIam/KA==",
"BVqe5rK1Fg1i+C7xXTAzT9vDPcf3kQQpTtse6rT/EVDzKo9AUo4ZwyUyJ0KcLHoffIjul/TuJoBg+wLz7Z7r7g==",
"WASmeku5Pcfz7N0Kp4Q3I9sxtO2MiaBXA418CY0HvjdtmAo7QY+K3E0o9UemgGzz41KqeypzRC92MwOAOnXJLA=="};
for (std::size_t i = 0; i < strings.size(); i++) {
td::string output(64, '\0');
td::hmac_sha512("cucumber", strings[i], output);
ASSERT_STREQ(answers[i], td::base64_encode(output));
}
}
#endif
#if TD_HAVE_ZLIB

View File

@ -711,3 +711,22 @@ TEST(Mtproto, TlsTransport) {
}
sched.finish();
}
TEST(Mtproto, RSA) {
auto pem = td::Slice(
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAr4v4wxMDXIaMOh8bayF/NyoYdpcysn5EbjTIOZC0RkgzsRj3SGlu\n"
"52QSz+ysO41dQAjpFLgxPVJoOlxXokaOq827IfW0bGCm0doT5hxtedu9UCQKbE8j\n"
"lDOk+kWMXHPZFJKWRgKgTu9hcB3y3Vk+JFfLpq3d5ZB48B4bcwrRQnzkx5GhWOFX\n"
"x73ZgjO93eoQ2b/lDyXxK4B4IS+hZhjzezPZTI5upTRbs5ljlApsddsHrKk6jJNj\n"
"8Ygs/ps8e6ct82jLXbnndC9s8HjEvDvBPH9IPjv5JUlmHMBFZ5vFQIfbpo0u0+1P\n"
"n6bkEi5o7/ifoyVv2pAZTRwppTz0EuXD8QIDAQAB\n"
"-----END RSA PUBLIC KEY-----");
auto rsa = RSA::from_pem_public_key(pem).move_as_ok();
ASSERT_EQ(-7596991558377038078, rsa.get_fingerprint());
ASSERT_EQ(256u, rsa.size());
string s(255, '\0');
string to(256, '\0');
ASSERT_EQ(256u, rsa.encrypt(MutableSlice(s).ubegin(), 10, 255, MutableSlice(to).ubegin(), 256));
}

View File

@ -162,7 +162,7 @@ class TestClient : public td::Actor {
td::Promise<> close_promise_;
};
class Task : public TestClient::Listener {
class TestClinetTask : public TestClient::Listener {
public:
void on_update(std::shared_ptr<TestClient::Update> update) override {
auto it = sent_queries_.find(update->id);
@ -198,7 +198,7 @@ class Task : public TestClient::Listener {
}
};
class DoAuthentication : public Task {
class DoAuthentication : public TestClinetTask {
public:
DoAuthentication(td::string name, td::string phone, td::string code, td::Promise<> promise)
: name_(std::move(name)), phone_(std::move(phone)), code_(std::move(code)), promise_(std::move(promise)) {
@ -274,7 +274,7 @@ class DoAuthentication : public Task {
}
};
class SetUsername : public Task {
class SetUsername : public TestClinetTask {
public:
SetUsername(td::string username, td::Promise<> promise)
: username_(std::move(username)), promise_(std::move(promise)) {
@ -339,7 +339,7 @@ class SetUsername : public Task {
}
};
class CheckTestA : public Task {
class CheckTestA : public TestClinetTask {
public:
CheckTestA(td::string tag, td::Promise<> promise) : tag_(std::move(tag)), promise_(std::move(promise)) {
}
@ -371,7 +371,7 @@ class CheckTestA : public Task {
}
};
class TestA : public Task {
class TestA : public TestClinetTask {
public:
TestA(td::string tag, td::string username) : tag_(std::move(tag)), username_(std::move(username)) {
}
@ -397,7 +397,7 @@ class TestA : public Task {
td::string username_;
};
class TestSecretChat : public Task {
class TestSecretChat : public TestClinetTask {
public:
TestSecretChat(td::string tag, td::string username) : tag_(std::move(tag)), username_(std::move(username)) {
}
@ -448,7 +448,7 @@ class TestSecretChat : public Task {
td::int64 chat_id_ = 0;
};
class TestFileGenerated : public Task {
class TestFileGenerated : public TestClinetTask {
public:
TestFileGenerated(td::string tag, td::string username) : tag_(std::move(tag)), username_(std::move(username)) {
}
@ -514,7 +514,7 @@ class TestFileGenerated : public Task {
class GenerateFile : public td::Actor {
public:
GenerateFile(Task *parent, td::int64 id, td::string original_path, td::string destination_path,
GenerateFile(TestClinetTask *parent, td::int64 id, td::string original_path, td::string destination_path,
td::string conversion)
: parent_(parent)
, id_(id)
@ -524,7 +524,7 @@ class TestFileGenerated : public Task {
}
private:
Task *parent_;
TestClinetTask *parent_;
td::int64 id_;
td::string original_path_;
td::string destination_path_;
@ -589,7 +589,7 @@ class TestFileGenerated : public Task {
td::int64 chat_id_ = 0;
};
class CheckTestC : public Task {
class CheckTestC : public TestClinetTask {
public:
CheckTestC(td::string username, td::string tag, td::Promise<> promise)
: username_(std::move(username)), tag_(std::move(tag)), promise_(std::move(promise)) {

View File

@ -10,18 +10,16 @@
#include "td/db/TQueue.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/int_types.h"
#include "td/utils/misc.h"
#include "td/utils/port/path.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/Span.h"
#include "td/utils/Status.h"
#include "td/utils/tests.h"
#include "td/utils/VectorQueue.h"
#include <map>
#include <set>
#include <memory>
#include <utility>
TEST(TQueue, hands) {
td::TQueue::Event events[100];