diff --git a/src/Cache.cpp b/src/Cache.cpp
index 5302218a..07d01819 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -139,24 +139,26 @@ Cache::Cache(const QString &userId, QObject *parent)
, localUserId_{userId}
{
setup();
- connect(this,
- &Cache::updateUserCacheFlag,
- this,
- [this](const std::string &user_id) {
- std::optional<UserCache> cache_ = getUserCache(user_id);
- if (cache_.has_value()) {
- cache_.value().isUpdated = false;
- setUserCache(user_id, cache_.value());
- } else {
- setUserCache(user_id, UserCache{});
- }
- },
- Qt::QueuedConnection);
- connect(this,
- &Cache::deleteLeftUsers,
- this,
- [this](const std::string &user_id) { deleteUserCache(user_id); },
- Qt::QueuedConnection);
+ connect(
+ this,
+ &Cache::updateUserCacheFlag,
+ this,
+ [this](const std::string &user_id) {
+ std::optional<UserCache> cache_ = getUserCache(user_id);
+ if (cache_.has_value()) {
+ cache_.value().isUpdated = false;
+ setUserCache(user_id, cache_.value());
+ } else {
+ setUserCache(user_id, UserCache{});
+ }
+ },
+ Qt::QueuedConnection);
+ connect(
+ this,
+ &Cache::deleteLeftUsers,
+ this,
+ [this](const std::string &user_id) { deleteUserCache(user_id); },
+ Qt::QueuedConnection);
}
void
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 31ba38d7..704543b5 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -606,11 +606,12 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
connect(
this, &ChatPage::tryInitialSyncCb, this, &ChatPage::tryInitialSync, Qt::QueuedConnection);
connect(this, &ChatPage::trySyncCb, this, &ChatPage::trySync, Qt::QueuedConnection);
- connect(this,
- &ChatPage::tryDelayedSyncCb,
- this,
- [this]() { QTimer::singleShot(RETRY_TIMEOUT, this, &ChatPage::trySync); },
- Qt::QueuedConnection);
+ connect(
+ this,
+ &ChatPage::tryDelayedSyncCb,
+ this,
+ [this]() { QTimer::singleShot(RETRY_TIMEOUT, this, &ChatPage::trySync); },
+ Qt::QueuedConnection);
connect(this,
&ChatPage::newSyncResponse,
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 9e997801..4f0c5893 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -581,9 +581,11 @@ send_megolm_key_to_device(const std::string &user_id,
->create_room_key_event(UserId(user_id), pks.ed25519, payload)
.dump();
+ mtx::requests::ClaimKeys claim_keys;
+ claim_keys.one_time_keys[user_id][device_id] = mtx::crypto::SIGNED_CURVE25519;
+
http::client()->claim_keys(
- user_id,
- {device_id},
+ claim_keys,
[room_key, user_id, device_id, pks](const mtx::responses::ClaimKeys &res,
mtx::http::RequestErr err) {
if (err) {
diff --git a/src/timeline/.TimelineModel.cpp.swn b/src/timeline/.TimelineModel.cpp.swn
new file mode 100644
index 00000000..9e965702
--- /dev/null
+++ b/src/timeline/.TimelineModel.cpp.swn
Binary files differdiff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 66a6d799..af1f7b23 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -32,38 +32,40 @@ EventStore::EventStore(std::string room_id, QObject *)
this->last = range->last;
}
- connect(this,
- &EventStore::eventFetched,
- this,
- [this](std::string id,
- std::string relatedTo,
- mtx::events::collections::TimelineEvents timeline) {
- cache::client()->storeEvent(room_id_, id, {timeline});
-
- if (!relatedTo.empty()) {
- auto idx = idToIndex(relatedTo);
- if (idx)
- emit dataChanged(*idx, *idx);
- }
- },
- Qt::QueuedConnection);
-
- connect(this,
- &EventStore::oldMessagesRetrieved,
- this,
- [this](const mtx::responses::Messages &res) {
- uint64_t newFirst = cache::client()->saveOldMessages(room_id_, res);
- if (newFirst == first)
- fetchMore();
- else {
- emit beginInsertRows(toExternalIdx(newFirst),
- toExternalIdx(this->first - 1));
- this->first = newFirst;
- emit endInsertRows();
- emit fetchedMore();
- }
- },
- Qt::QueuedConnection);
+ connect(
+ this,
+ &EventStore::eventFetched,
+ this,
+ [this](std::string id,
+ std::string relatedTo,
+ mtx::events::collections::TimelineEvents timeline) {
+ cache::client()->storeEvent(room_id_, id, {timeline});
+
+ if (!relatedTo.empty()) {
+ auto idx = idToIndex(relatedTo);
+ if (idx)
+ emit dataChanged(*idx, *idx);
+ }
+ },
+ Qt::QueuedConnection);
+
+ connect(
+ this,
+ &EventStore::oldMessagesRetrieved,
+ this,
+ [this](const mtx::responses::Messages &res) {
+ uint64_t newFirst = cache::client()->saveOldMessages(room_id_, res);
+ if (newFirst == first)
+ fetchMore();
+ else {
+ emit beginInsertRows(toExternalIdx(newFirst),
+ toExternalIdx(this->first - 1));
+ this->first = newFirst;
+ emit endInsertRows();
+ emit fetchedMore();
+ }
+ },
+ Qt::QueuedConnection);
connect(this, &EventStore::processPending, this, [this]() {
if (!current_txn.empty()) {
@@ -128,46 +130,48 @@ EventStore::EventStore(std::string room_id, QObject *)
event->data);
});
- connect(this,
- &EventStore::messageFailed,
- this,
- [this](std::string txn_id) {
- if (current_txn == txn_id) {
- current_txn_error_count++;
- if (current_txn_error_count > 10) {
- nhlog::ui()->debug("failing txn id '{}'", txn_id);
- cache::client()->removePendingStatus(room_id_, txn_id);
- current_txn_error_count = 0;
- }
- }
- QTimer::singleShot(1000, this, [this]() {
- nhlog::ui()->debug("timeout");
- this->current_txn = "";
- emit processPending();
- });
- },
- Qt::QueuedConnection);
-
- connect(this,
- &EventStore::messageSent,
- this,
- [this](std::string txn_id, std::string event_id) {
- nhlog::ui()->debug("sent {}", txn_id);
-
- http::client()->read_event(
- room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
- if (err) {
- nhlog::net()->warn(
- "failed to read_event ({}, {})", room_id_, event_id);
- }
- });
-
- cache::client()->removePendingStatus(room_id_, txn_id);
- this->current_txn = "";
- this->current_txn_error_count = 0;
- emit processPending();
- },
- Qt::QueuedConnection);
+ connect(
+ this,
+ &EventStore::messageFailed,
+ this,
+ [this](std::string txn_id) {
+ if (current_txn == txn_id) {
+ current_txn_error_count++;
+ if (current_txn_error_count > 10) {
+ nhlog::ui()->debug("failing txn id '{}'", txn_id);
+ cache::client()->removePendingStatus(room_id_, txn_id);
+ current_txn_error_count = 0;
+ }
+ }
+ QTimer::singleShot(1000, this, [this]() {
+ nhlog::ui()->debug("timeout");
+ this->current_txn = "";
+ emit processPending();
+ });
+ },
+ Qt::QueuedConnection);
+
+ connect(
+ this,
+ &EventStore::messageSent,
+ this,
+ [this](std::string txn_id, std::string event_id) {
+ nhlog::ui()->debug("sent {}", txn_id);
+
+ http::client()->read_event(
+ room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
+ if (err) {
+ nhlog::net()->warn(
+ "failed to read_event ({}, {})", room_id_, event_id);
+ }
+ });
+
+ cache::client()->removePendingStatus(room_id_, txn_id);
+ this->current_txn = "";
+ this->current_txn_error_count = 0;
+ emit processPending();
+ },
+ Qt::QueuedConnection);
}
void
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 8f0e470e..ddd238b9 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -204,11 +204,12 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
, room_id_(room_id)
, manager_(manager)
{
- connect(this,
- &TimelineModel::redactionFailed,
- this,
- [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
- Qt::QueuedConnection);
+ connect(
+ this,
+ &TimelineModel::redactionFailed,
+ this,
+ [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
+ Qt::QueuedConnection);
connect(this,
&TimelineModel::newMessageToSend,
@@ -217,17 +218,17 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
Qt::QueuedConnection);
connect(this, &TimelineModel::addPendingMessageToStore, &events, &EventStore::addPending);
- connect(&events,
- &EventStore::dataChanged,
- this,
- [this](int from, int to) {
- nhlog::ui()->debug("data changed {} to {}",
- events.size() - to - 1,
- events.size() - from - 1);
- emit dataChanged(index(events.size() - to - 1, 0),
- index(events.size() - from - 1, 0));
- },
- Qt::QueuedConnection);
+ connect(
+ &events,
+ &EventStore::dataChanged,
+ this,
+ [this](int from, int to) {
+ nhlog::ui()->debug(
+ "data changed {} to {}", events.size() - to - 1, events.size() - from - 1);
+ emit dataChanged(index(events.size() - to - 1, 0),
+ index(events.size() - from - 1, 0));
+ },
+ Qt::QueuedConnection);
connect(&events, &EventStore::beginInsertRows, this, [this](int from, int to) {
int first = events.size() - to;
@@ -916,10 +917,20 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::
OutboundGroupSessionData session_data;
session_data.session_id = session_id;
session_data.session_key = session_key;
- session_data.message_index = 0; // TODO Update me
+ session_data.message_index = 0;
cache::saveOutboundMegolmSession(
room_id, session_data, std::move(outbound_session));
+ {
+ MegolmSessionIndex index;
+ index.room_id = room_id;
+ index.session_id = session_id;
+ index.sender_key = olm::client()->identity_keys().curve25519;
+ auto megolm_session =
+ olm::client()->init_inbound_group_session(session_key);
+ cache::saveInboundMegolmSession(index, std::move(megolm_session));
+ }
+
const auto members = cache::roomMembers(room_id);
nhlog::ui()->info("retrieved {} members for {}", members.size(), room_id);
@@ -961,19 +972,23 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::
return;
}
- for (const auto &user : res.device_keys) {
- // Mapping from a device_id with valid identity keys to the
- // generated room_key event used for sharing the megolm session.
- std::map<std::string, std::string> room_key_msgs;
- std::map<std::string, DevicePublicKeys> deviceKeys;
+ mtx::requests::ClaimKeys claim_keys;
- room_key_msgs.clear();
- deviceKeys.clear();
+ // Mapping from user id to a device_id with valid identity keys to the
+ // generated room_key event used for sharing the megolm session.
+ std::map<std::string, std::map<std::string, std::string>> room_key_msgs;
+ std::map<std::string, std::map<std::string, DevicePublicKeys>> deviceKeys;
+ for (const auto &user : res.device_keys) {
for (const auto &dev : user.second) {
const auto user_id = ::UserId(dev.second.user_id);
const auto device_id = DeviceId(dev.second.device_id);
+ if (user_id.get() ==
+ http::client()->user_id().to_string() &&
+ device_id.get() == http::client()->device_id())
+ continue;
+
const auto device_keys = dev.second.keys;
const auto curveKey = "curve25519:" + device_id.get();
const auto edKey = "ed25519:" + device_id.get();
@@ -1015,42 +1030,25 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::
user_id, pks.ed25519, megolm_payload)
.dump();
- room_key_msgs.emplace(device_id, room_key);
- deviceKeys.emplace(device_id, pks);
- }
-
- std::vector<std::string> valid_devices;
- valid_devices.reserve(room_key_msgs.size());
- for (auto const &d : room_key_msgs) {
- valid_devices.push_back(d.first);
+ room_key_msgs[user_id].emplace(device_id, room_key);
+ deviceKeys[user_id].emplace(device_id, pks);
+ claim_keys.one_time_keys[user.first][device_id] =
+ mtx::crypto::SIGNED_CURVE25519;
- nhlog::net()->info("{}", d.first);
- nhlog::net()->info(" curve25519 {}",
- deviceKeys.at(d.first).curve25519);
- nhlog::net()->info(" ed25519 {}",
- deviceKeys.at(d.first).ed25519);
+ nhlog::net()->info("{}", device_id.get());
+ nhlog::net()->info(" curve25519 {}", pks.curve25519);
+ nhlog::net()->info(" ed25519 {}", pks.ed25519);
}
-
- nhlog::net()->info(
- "sending claim request for user {} with {} devices",
- user.first,
- valid_devices.size());
-
- http::client()->claim_keys(
- user.first,
- valid_devices,
- std::bind(&TimelineModel::handleClaimedKeys,
- this,
- keeper,
- room_key_msgs,
- deviceKeys,
- user.first,
- std::placeholders::_1,
- std::placeholders::_2));
-
- // TODO: Wait before sending the next batch of requests.
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
+
+ http::client()->claim_keys(claim_keys,
+ std::bind(&TimelineModel::handleClaimedKeys,
+ this,
+ keeper,
+ room_key_msgs,
+ deviceKeys,
+ std::placeholders::_1,
+ std::placeholders::_2));
});
// TODO: Let the user know about the errors.
@@ -1068,12 +1066,12 @@ TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::
}
void
-TimelineModel::handleClaimedKeys(std::shared_ptr<StateKeeper> keeper,
- const std::map<std::string, std::string> &room_keys,
- const std::map<std::string, DevicePublicKeys> &pks,
- const std::string &user_id,
- const mtx::responses::ClaimKeys &res,
- mtx::http::RequestErr err)
+TimelineModel::handleClaimedKeys(
+ std::shared_ptr<StateKeeper> keeper,
+ const std::map<std::string, std::map<std::string, std::string>> &room_keys,
+ const std::map<std::string, std::map<std::string, DevicePublicKeys>> &pks,
+ const mtx::responses::ClaimKeys &res,
+ mtx::http::RequestErr err)
{
if (err) {
nhlog::net()->warn("claim keys error: {} {} {}",
@@ -1083,65 +1081,53 @@ TimelineModel::handleClaimedKeys(std::shared_ptr<StateKeeper> keeper,
return;
}
- nhlog::net()->debug("claimed keys for {}", user_id);
-
- if (res.one_time_keys.size() == 0) {
- nhlog::net()->debug("no one-time keys found for user_id: {}", user_id);
- return;
- }
-
- if (res.one_time_keys.find(user_id) == res.one_time_keys.end()) {
- nhlog::net()->debug("no one-time keys found for user_id: {}", user_id);
- return;
- }
-
- auto retrieved_devices = res.one_time_keys.at(user_id);
-
// Payload with all the to_device message to be sent.
- json body;
- body["messages"][user_id] = json::object();
+ nlohmann::json body;
- for (const auto &rd : retrieved_devices) {
- const auto device_id = rd.first;
- nhlog::net()->debug("{} : \n {}", device_id, rd.second.dump(2));
+ for (const auto &[user_id, retrieved_devices] : res.one_time_keys) {
+ nhlog::net()->debug("claimed keys for {}", user_id);
+ if (retrieved_devices.size() == 0) {
+ nhlog::net()->debug("no one-time keys found for user_id: {}", user_id);
+ return;
+ }
- // TODO: Verify signatures
- auto otk = rd.second.begin()->at("key");
+ for (const auto &rd : retrieved_devices) {
+ const auto device_id = rd.first;
- if (pks.find(device_id) == pks.end()) {
- nhlog::net()->critical("couldn't find public key for device: {}",
- device_id);
- continue;
- }
+ nhlog::net()->debug("{} : \n {}", device_id, rd.second.dump(2));
- auto id_key = pks.at(device_id).curve25519;
- auto s = olm::client()->create_outbound_session(id_key, otk);
+ // TODO: Verify signatures
+ auto otk = rd.second.begin()->at("key");
- if (room_keys.find(device_id) == room_keys.end()) {
- nhlog::net()->critical("couldn't find m.room_key for device: {}",
- device_id);
- continue;
- }
+ auto id_key = pks.at(user_id).at(device_id).curve25519;
+ auto s = olm::client()->create_outbound_session(id_key, otk);
+
+ auto device_msg = olm::client()->create_olm_encrypted_content(
+ s.get(),
+ room_keys.at(user_id).at(device_id),
+ pks.at(user_id).at(device_id).curve25519);
- auto device_msg = olm::client()->create_olm_encrypted_content(
- s.get(), room_keys.at(device_id), pks.at(device_id).curve25519);
+ try {
+ cache::saveOlmSession(id_key, std::move(s));
+ } catch (const lmdb::error &e) {
+ nhlog::db()->critical("failed to save outbound olm session: {}",
+ e.what());
+ } catch (const mtx::crypto::olm_exception &e) {
+ nhlog::crypto()->critical(
+ "failed to pickle outbound olm session: {}", e.what());
+ }
- try {
- cache::saveOlmSession(id_key, std::move(s));
- } catch (const lmdb::error &e) {
- nhlog::db()->critical("failed to save outbound olm session: {}", e.what());
- } catch (const mtx::crypto::olm_exception &e) {
- nhlog::crypto()->critical("failed to pickle outbound olm session: {}",
- e.what());
+ body["messages"][user_id][device_id] = device_msg;
}
- body["messages"][user_id][device_id] = device_msg;
+ nhlog::net()->info("send_to_device: {}", user_id);
}
- nhlog::net()->info("send_to_device: {}", user_id);
-
http::client()->send_to_device(
- "m.room.encrypted", body, [keeper](mtx::http::RequestErr err) {
+ mtx::events::to_string(mtx::events::EventType::RoomEncrypted),
+ http::client()->generate_txn_id(),
+ body,
+ [keeper](mtx::http::RequestErr err) {
if (err) {
nhlog::net()->warn("failed to send "
"send_to_device "
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 390fa1ed..61d00df9 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -285,12 +285,12 @@ signals:
private:
template<typename T>
void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType);
- void handleClaimedKeys(std::shared_ptr<StateKeeper> keeper,
- const std::map<std::string, std::string> &room_key,
- const std::map<std::string, DevicePublicKeys> &pks,
- const std::string &user_id,
- const mtx::responses::ClaimKeys &res,
- mtx::http::RequestErr err);
+ void handleClaimedKeys(
+ std::shared_ptr<StateKeeper> keeper,
+ const std::map<std::string, std::map<std::string, std::string>> &room_keys,
+ const std::map<std::string, std::map<std::string, DevicePublicKeys>> &pks,
+ const mtx::responses::ClaimKeys &res,
+ mtx::http::RequestErr err);
void readEvent(const std::string &id);
void setPaginationInProgress(const bool paginationInProgress);
|