Add use_custom_database_format option
This commit is contained in:
parent
09b98f6b30
commit
46c0f5877d
6
.gitignore
vendored
6
.gitignore
vendored
@ -9,3 +9,9 @@ docs/
|
|||||||
.idea/
|
.idea/
|
||||||
vcpkg/
|
vcpkg/
|
||||||
*.tlo
|
*.tlo
|
||||||
|
|
||||||
|
td.binlog
|
||||||
|
|
||||||
|
tg_cli.log
|
||||||
|
|
||||||
|
tg_cli.log.old
|
||||||
|
@ -87,6 +87,56 @@ class Global final : public ActorContext {
|
|||||||
|
|
||||||
Status init(const TdParameters ¶meters, ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) TD_WARN_UNUSED_RESULT;
|
Status init(const TdParameters ¶meters, ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) TD_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
static bool get_use_custom_database(const std::string &database_directory) {
|
||||||
|
auto s = get_database_directory_opts(database_directory);
|
||||||
|
size_t qmarkpos;
|
||||||
|
std::string token;
|
||||||
|
size_t find_start_index = 0;
|
||||||
|
while ((qmarkpos = s.find_first_of('&'), find_start_index) != std::string::npos) {
|
||||||
|
token = s.substr(find_start_index, qmarkpos - find_start_index);
|
||||||
|
find_start_index = qmarkpos;
|
||||||
|
if ((qmarkpos = token.find_first_of('=')) != std::string::npos) {
|
||||||
|
std::string propkey = token.substr(0, qmarkpos), propval = token.substr(qmarkpos + 1);
|
||||||
|
if (propkey == "use_custom_database_format" && propval == "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string get_database_directory_path(const std::string &database_directory) {
|
||||||
|
if (database_directory.empty()) {
|
||||||
|
return database_directory;
|
||||||
|
}
|
||||||
|
size_t qmarkpos;
|
||||||
|
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
|
||||||
|
std::string path = database_directory.substr(0, qmarkpos),
|
||||||
|
opts = database_directory.substr(qmarkpos + 1);
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
return database_directory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string get_database_directory_opts(const std::string &database_directory) {
|
||||||
|
if (database_directory.empty()) {
|
||||||
|
return database_directory;
|
||||||
|
}
|
||||||
|
size_t qmarkpos;
|
||||||
|
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
|
||||||
|
std::string path = database_directory.substr(0, qmarkpos),
|
||||||
|
opts = database_directory.substr(qmarkpos + 1);
|
||||||
|
return opts;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_use_custom_database() const {
|
||||||
|
return parameters_.use_custom_db_format;
|
||||||
|
};
|
||||||
|
|
||||||
Slice get_dir() const {
|
Slice get_dir() const {
|
||||||
return parameters_.database_directory;
|
return parameters_.database_directory;
|
||||||
}
|
}
|
||||||
|
@ -3007,12 +3007,15 @@ td_api::object_ptr<td_api::AuthorizationState> Td::get_fake_authorization_state_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DbKey Td::as_db_key(string key) {
|
DbKey Td::as_db_key(string key, bool custom_db) {
|
||||||
// Database will still be effectively not encrypted, but
|
// Database will still be effectively not encrypted, but
|
||||||
// 1. SQLite database will be protected from corruption, because that's how sqlcipher works
|
// 1. SQLite database will be protected from corruption, because that's how sqlcipher works
|
||||||
// 2. security through obscurity
|
// 2. security through obscurity
|
||||||
// 3. no need for reencryption of SQLite database
|
// 3. no need for reencryption of SQLite database
|
||||||
if (key.empty()) {
|
if (key.empty()) {
|
||||||
|
if (custom_db) {
|
||||||
|
return DbKey::empty();
|
||||||
|
}
|
||||||
return DbKey::raw_key("cucumber");
|
return DbKey::raw_key("cucumber");
|
||||||
}
|
}
|
||||||
return DbKey::raw_key(std::move(key));
|
return DbKey::raw_key(std::move(key));
|
||||||
@ -3080,11 +3083,11 @@ void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
|
|||||||
switch (function_id) {
|
switch (function_id) {
|
||||||
case td_api::checkDatabaseEncryptionKey::ID: {
|
case td_api::checkDatabaseEncryptionKey::ID: {
|
||||||
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(function);
|
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(function);
|
||||||
return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_))));
|
return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_), parameters_.use_custom_db_format)));
|
||||||
}
|
}
|
||||||
case td_api::setDatabaseEncryptionKey::ID: {
|
case td_api::setDatabaseEncryptionKey::ID: {
|
||||||
auto set_key = move_tl_object_as<td_api::setDatabaseEncryptionKey>(function);
|
auto set_key = move_tl_object_as<td_api::setDatabaseEncryptionKey>(function);
|
||||||
return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_))));
|
return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_), parameters_.use_custom_db_format)));
|
||||||
}
|
}
|
||||||
case td_api::destroy::ID:
|
case td_api::destroy::ID:
|
||||||
// need to send response synchronously before actual destroying
|
// need to send response synchronously before actual destroying
|
||||||
@ -4245,7 +4248,8 @@ Status Td::set_parameters(td_api::object_ptr<td_api::tdlibParameters> parameters
|
|||||||
}
|
}
|
||||||
|
|
||||||
parameters_.use_test_dc = parameters->use_test_dc_;
|
parameters_.use_test_dc = parameters->use_test_dc_;
|
||||||
parameters_.database_directory = parameters->database_directory_;
|
parameters_.database_directory = Global::get_database_directory_path(parameters->database_directory_);
|
||||||
|
parameters_.use_custom_db_format = Global::get_use_custom_database(parameters->database_directory_);
|
||||||
parameters_.files_directory = parameters->files_directory_;
|
parameters_.files_directory = parameters->files_directory_;
|
||||||
parameters_.api_id = parameters->api_id_;
|
parameters_.api_id = parameters->api_id_;
|
||||||
parameters_.api_hash = parameters->api_hash_;
|
parameters_.api_hash = parameters->api_hash_;
|
||||||
@ -4310,7 +4314,7 @@ void Td::on_request(uint64 id, const td_api::checkDatabaseEncryptionKey &request
|
|||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) {
|
void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) {
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_)), std::move(promise));
|
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_), parameters_.use_custom_db_format), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getAuthorizationState &request) {
|
void Td::on_request(uint64 id, const td_api::getAuthorizationState &request) {
|
||||||
|
@ -1344,7 +1344,7 @@ class Td final : public Actor {
|
|||||||
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
|
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
|
||||||
static td_api::object_ptr<td_api::Object> do_static_request(td_api::testReturnError &request);
|
static td_api::object_ptr<td_api::Object> do_static_request(td_api::testReturnError &request);
|
||||||
|
|
||||||
static DbKey as_db_key(string key);
|
static DbKey as_db_key(string key, bool custom_db);
|
||||||
Status init(DbKey key) TD_WARN_UNUSED_RESULT;
|
Status init(DbKey key) TD_WARN_UNUSED_RESULT;
|
||||||
void init_options_and_network();
|
void init_options_and_network();
|
||||||
void init_connection_creator();
|
void init_connection_creator();
|
||||||
|
@ -303,8 +303,16 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, con
|
|||||||
sql_connection_ = std::make_shared<SqliteConnectionSafe>(sql_database_path, key, db_instance.get_cipher_version());
|
sql_connection_ = std::make_shared<SqliteConnectionSafe>(sql_database_path, key, db_instance.get_cipher_version());
|
||||||
sql_connection_->set(std::move(db_instance));
|
sql_connection_->set(std::move(db_instance));
|
||||||
auto &db = sql_connection_->get();
|
auto &db = sql_connection_->get();
|
||||||
|
if (parameters.use_custom_db_format) {
|
||||||
|
TRY_STATUS(db.exec("PRAGMA journal_mode=OFF"));
|
||||||
|
TRY_STATUS(db.exec("PRAGMA synchronous=OFF"))
|
||||||
|
TRY_STATUS(db.exec("PRAGMA temp_store=MEMORY"));
|
||||||
|
TRY_STATUS(db.exec("PRAGMA secure_delete=0"));
|
||||||
|
TRY_STATUS(db.exec("PRAGMA mmap_size=30000000000"));
|
||||||
|
} else {
|
||||||
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
|
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
|
||||||
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
|
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
|
||||||
|
}
|
||||||
|
|
||||||
// Init databases
|
// Init databases
|
||||||
// Do initialization once and before everything else to avoid "database is locked" error.
|
// Do initialization once and before everything else to avoid "database is locked" error.
|
||||||
|
@ -23,6 +23,7 @@ struct TdParameters {
|
|||||||
bool use_secret_chats = false;
|
bool use_secret_chats = false;
|
||||||
bool use_chat_info_db = false;
|
bool use_chat_info_db = false;
|
||||||
bool use_message_db = false;
|
bool use_message_db = false;
|
||||||
|
bool use_custom_db_format = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
Loading…
Reference in New Issue
Block a user