Support subscribing for encrypted push notifications.

GitOrigin-RevId: ff0bc71f137cc0d77df4297ef22e8a885864f27b
This commit is contained in:
levlam 2018-12-24 18:33:39 +03:00
parent 531bf775a3
commit bbcad65737
6 changed files with 66 additions and 8 deletions

View File

@ -1739,14 +1739,14 @@ localizationTargetInfo language_packs:vector<languagePackInfo> = LocalizationTar
//@class DeviceToken @description Represents a data needed to subscribe for push notifications through registerDevice method. To use specific push notification service, you must specify the correct application platform and upload valid server authentication data at https://my.telegram.org
//@description A token for Google Cloud Messaging @token Device registration token; may be empty to de-register a device
deviceTokenGoogleCloudMessaging token:string = DeviceToken;
//@description A token for Google Cloud Messaging @token Device registration token; may be empty to de-register a device @encrypt True, if push notifications should be additionally encrypted
deviceTokenGoogleCloudMessaging token:string encrypt:Bool = DeviceToken;
//@description A token for Apple Push Notification service @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled
deviceTokenApplePush device_token:string is_app_sandbox:Bool = DeviceToken;
//@description A token for Apple Push Notification service VoIP notifications @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled
deviceTokenApplePushVoIP device_token:string is_app_sandbox:Bool = DeviceToken;
//@description A token for Apple Push Notification service VoIP notifications @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled @encrypt True, if push notifications should be additionally encrypted
deviceTokenApplePushVoIP device_token:string is_app_sandbox:Bool encrypt:Bool = DeviceToken;
//@description A token for Windows Push Notification Services @access_token The access token that will be used to send notifications; may be empty to de-register a device
deviceTokenWindowsPush access_token:string = DeviceToken;

Binary file not shown.

View File

@ -19,6 +19,7 @@
#include "td/utils/format.h"
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/Random.h"
#include "td/utils/Status.h"
#include "td/utils/tl_helpers.h"
@ -39,11 +40,15 @@ void DeviceTokenManager::TokenInfo::store(StorerT &storer) const {
STORE_FLAG(is_unregister);
STORE_FLAG(is_register);
STORE_FLAG(is_app_sandbox);
STORE_FLAG(encrypt);
END_STORE_FLAGS();
store(token, storer);
if (has_other_user_ids) {
store(other_user_ids, storer);
}
if (encrypt) {
store(encryption_key, storer);
}
}
template <class ParserT>
@ -59,6 +64,7 @@ void DeviceTokenManager::TokenInfo::parse(ParserT &parser) {
PARSE_FLAG(is_unregister);
PARSE_FLAG(is_register);
PARSE_FLAG(is_app_sandbox);
PARSE_FLAG(encrypt);
END_PARSE_FLAGS_GENERIC();
CHECK(is_sync + is_unregister + is_register == 1);
if (is_sync) {
@ -72,6 +78,9 @@ void DeviceTokenManager::TokenInfo::parse(ParserT &parser) {
if (has_other_user_ids) {
parse(other_user_ids, parser);
}
if (encrypt) {
parse(encryption_key, parser);
}
}
StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManager::TokenInfo &token_info) {
@ -95,6 +104,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManage
if (token_info.is_app_sandbox) {
string_builder << ", sandboxed";
}
if (token_info.encrypt) {
string_builder << ", encrypted";
}
return string_builder;
}
@ -104,6 +116,7 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
TokenType token_type;
string token;
bool is_app_sandbox = false;
bool encrypt = false;
switch (device_token_ptr->get_id()) {
case td_api::deviceTokenApplePush::ID: {
auto device_token = static_cast<td_api::deviceTokenApplePush *>(device_token_ptr.get());
@ -116,6 +129,7 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
auto device_token = static_cast<td_api::deviceTokenGoogleCloudMessaging *>(device_token_ptr.get());
token = std::move(device_token->token_);
token_type = TokenType::GCM;
encrypt = device_token->encrypt_;
break;
}
case td_api::deviceTokenMicrosoftPush::ID: {
@ -153,6 +167,7 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
token = std::move(device_token->device_token_);
token_type = TokenType::APNS_VOIP;
is_app_sandbox = device_token->is_app_sandbox_;
encrypt = device_token->encrypt_;
break;
}
case td_api::deviceTokenWebPush::ID: {
@ -226,11 +241,32 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
}
info.other_user_ids = std::move(other_user_ids);
info.is_app_sandbox = is_app_sandbox;
if (encrypt != info.encrypt) {
if (encrypt) {
constexpr size_t ENCRYPTION_KEY_LENGTH = 256;
info.encryption_key.resize(ENCRYPTION_KEY_LENGTH);
Random::secure_bytes(info.encryption_key);
} else {
info.encryption_key.clear();
}
info.encrypt = encrypt;
}
info.promise.set_value(make_tl_object<td_api::ok>());
info.promise = std::move(promise);
save_info(token_type);
}
vector<Slice> DeviceTokenManager::get_encryption_keys() const {
vector<Slice> result;
for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) {
auto &info = tokens_[token_type];
if (!info.token.empty() && info.encrypt && info.state != TokenInfo::State::Unregister) {
result.push_back(info.encryption_key);
}
}
return result;
}
string DeviceTokenManager::get_database_key(int32 token_type) {
return PSTRING() << "device_token" << token_type;
}
@ -302,7 +338,7 @@ void DeviceTokenManager::loop() {
create_storer(telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids))));
} else {
net_query = G()->net_query_creator().create(create_storer(telegram_api::account_registerDevice(
token_type, info.token, info.is_app_sandbox, BufferSlice(), std::move(other_user_ids))));
token_type, info.token, info.is_app_sandbox, BufferSlice(info.encryption_key), std::move(other_user_ids))));
}
info.net_query_id = net_query->id();
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type));
@ -329,7 +365,7 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) {
info.promise.set_value(make_tl_object<td_api::ok>());
}
if (info.state == TokenInfo::State::Unregister) {
info.token = "";
info.token.clear();
}
info.state = TokenInfo::State::Sync;
} else {
@ -344,7 +380,7 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) {
info.state = TokenInfo::State::Unregister;
} else {
info.state = TokenInfo::State::Sync;
info.token = "";
info.token.clear();
}
if (r_flag.is_error()) {
LOG(ERROR) << r_flag.error();

View File

@ -14,6 +14,7 @@
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/StringBuilder.h"
#include <array>
@ -27,6 +28,8 @@ class DeviceTokenManager : public NetQueryCallback {
void register_device(tl_object_ptr<td_api::DeviceToken> device_token_ptr, vector<int32> other_user_ids,
Promise<tl_object_ptr<td_api::ok>> promise);
vector<Slice> get_encryption_keys() const;
private:
static constexpr size_t MAX_OTHER_USER_IDS = 100;
@ -53,6 +56,8 @@ class DeviceTokenManager : public NetQueryCallback {
uint64 net_query_id = 0;
vector<int32> other_user_ids;
bool is_app_sandbox = false;
bool encrypt = false;
string encryption_key;
Promise<tl_object_ptr<td_api::ok>> promise;
template <class StorerT>

View File

@ -9,11 +9,13 @@
#include "td/telegram/AuthManager.h"
#include "td/telegram/ConfigShared.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DeviceTokenManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
@ -1869,7 +1871,19 @@ void NotificationManager::on_notification_default_delay_changed() {
}
void NotificationManager::process_push_notification(const string &payload, Promise<Unit> &&promise) {
if (G()->close_flag()) {
return;
}
auto encryption_keys = td_->device_token_manager_->get_actor_unsafe()->get_encryption_keys();
for (auto &key : encryption_keys) {
VLOG(notifications) << "Have key \"" << format::escaped(key) << '"';
}
if (encryption_keys.empty()) {
VLOG(notifications) << "Process push notification \"" << payload << '"';
} else {
VLOG(notifications) << "Process encrypted push notification \"" << format::escaped(payload) << '"';
}
promise.set_value(Unit());
}

View File

@ -1367,6 +1367,9 @@ class CliClient final : public Actor {
} else if (op == "rdb") {
send_request(make_tl_object<td_api::registerDevice>(make_tl_object<td_api::deviceTokenBlackBerryPush>(args),
as_user_ids("")));
} else if (op == "rdg") {
send_request(make_tl_object<td_api::registerDevice>(
make_tl_object<td_api::deviceTokenGoogleCloudMessaging>(args, true), as_user_ids("")));
} else if (op == "rdt") {
string token;
string other_user_ids_str;