diff --git a/include/Cache.h b/include/Cache.h index 97133b0c..76266ebd 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -355,7 +355,7 @@ public: // // Outbound Megolm Sessions // - void saveOutboundMegolmSession(const MegolmSessionIndex &index, + void saveOutboundMegolmSession(const std::string &room_id, const OutboundGroupSessionData &data, mtx::crypto::OutboundGroupSessionPtr session); OutboundGroupSessionDataRef getOutboundMegolmSession(const MegolmSessionIndex &index); diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h index 88857222..2c369d5f 100644 --- a/include/timeline/TimelineView.h +++ b/include/timeline/TimelineView.h @@ -48,8 +48,37 @@ struct PendingMessage uint64_t media_size; QString event_id; TimelineItem *widget; + bool is_encrypted = false; }; +template +MessageT +toRoomMessage(const PendingMessage &) = delete; + +template<> +mtx::events::msg::Audio +toRoomMessage(const PendingMessage &m); + +template<> +mtx::events::msg::Emote +toRoomMessage(const PendingMessage &m); + +template<> +mtx::events::msg::File +toRoomMessage(const PendingMessage &); + +template<> +mtx::events::msg::Image +toRoomMessage(const PendingMessage &m); + +template<> +mtx::events::msg::Text +toRoomMessage(const PendingMessage &); + +template<> +mtx::events::msg::Video +toRoomMessage(const PendingMessage &m); + // In which place new TimelineItems should be inserted. enum class TimelineDirection { @@ -318,7 +347,7 @@ TimelineView::addUserMessage(const QString &url, PendingMessage message; message.ty = MsgType; - message.txn_id = mtx::client::utils::random_token(); + message.txn_id = http::v2::client()->generate_txn_id(); message.body = url; message.filename = trimmed; message.mime = mime; diff --git a/src/Cache.cc b/src/Cache.cc index abc6fae4..35ad8f9d 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -251,12 +251,11 @@ Cache::inboundMegolmSessionExists(const MegolmSessionIndex &index) noexcept } void -Cache::saveOutboundMegolmSession(const MegolmSessionIndex &index, +Cache::saveOutboundMegolmSession(const std::string &room_id, const OutboundGroupSessionData &data, mtx::crypto::OutboundGroupSessionPtr session) { using namespace mtx::crypto; - const auto key = index.to_hash(); const auto pickled = pickle(session.get(), SECRET); json j; @@ -264,13 +263,13 @@ Cache::saveOutboundMegolmSession(const MegolmSessionIndex &index, j["session"] = pickled; auto txn = lmdb::txn::begin(env_); - lmdb::dbi_put(txn, outboundMegolmSessionDb_, lmdb::val(key), lmdb::val(j.dump())); + lmdb::dbi_put(txn, outboundMegolmSessionDb_, lmdb::val(room_id), lmdb::val(j.dump())); txn.commit(); { std::unique_lock lock(session_storage.group_outbound_mtx); - session_storage.group_outbound_session_data[key] = data; - session_storage.group_outbound_sessions[key] = std::move(session); + session_storage.group_outbound_session_data[room_id] = data; + session_storage.group_outbound_sessions[room_id] = std::move(session); } } @@ -302,7 +301,7 @@ Cache::saveOutboundOlmSession(const std::string &curve25519, mtx::crypto::OlmSes const auto pickled = pickle(session.get(), SECRET); auto txn = lmdb::txn::begin(env_); - lmdb::dbi_put(txn, outboundMegolmSessionDb_, lmdb::val(curve25519), lmdb::val(pickled)); + lmdb::dbi_put(txn, outboundOlmSessionDb_, lmdb::val(curve25519), lmdb::val(pickled)); txn.commit(); { @@ -372,8 +371,8 @@ Cache::restoreSessions() unpickle(obj.at("session"), SECRET); session_storage.group_outbound_sessions[key] = std::move(session); } catch (const nlohmann::json::exception &e) { - log::db()->warn("failed to parse outbound megolm session data: {}", - e.what()); + log::db()->critical( + "failed to parse outbound megolm session data: {}", e.what()); } } cursor.close(); diff --git a/src/timeline/TimelineView.cc b/src/timeline/TimelineView.cc index d004a543..67da5dc6 100644 --- a/src/timeline/TimelineView.cc +++ b/src/timeline/TimelineView.cc @@ -285,7 +285,12 @@ TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents & parseEncryptedEvent(mpark::get>(event)); return parseMessageEvent(decrypted, direction); } else if (mpark::holds_alternative>(event)) { - cache::client()->setEncryptedRoom(room_id_.toStdString()); + try { + cache::client()->setEncryptedRoom(room_id_.toStdString()); + } catch (const lmdb::error &e) { + log::db()->critical("failed to save room {} as encrypted", + room_id_.toStdString()); + } } return nullptr; @@ -588,6 +593,7 @@ TimelineView::addTimelineItem(TimelineItem *item, TimelineDirection direction) void TimelineView::updatePendingMessage(const std::string &txn_id, const QString &event_id) { + log::main()->info("[{}] message was received by the server", txn_id); if (!pending_msgs_.isEmpty() && pending_msgs_.head().txn_id == txn_id) { // We haven't received it yet auto msg = pending_msgs_.dequeue(); @@ -613,19 +619,28 @@ TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body) TimelineItem *view_item = new TimelineItem(ty, local_user_, body, with_sender, room_id_, scroll_widget_); + PendingMessage message; + message.ty = ty; + message.txn_id = http::v2::client()->generate_txn_id(); + message.body = body; + message.widget = view_item; + + try { + message.is_encrypted = cache::client()->isRoomEncrypted(room_id_.toStdString()); + } catch (const lmdb::error &e) { + log::db()->critical("failed to check encryption status of room {}", e.what()); + view_item->deleteLater(); + + // TODO: Send a notification to the user. + + return; + } + addTimelineItem(view_item); lastMessageDirection_ = TimelineDirection::Bottom; - QApplication::processEvents(); - saveLastMessageInfo(local_user_, QDateTime::currentDateTime()); - - PendingMessage message; - message.ty = ty; - message.txn_id = mtx::client::utils::random_token(); - message.body = body; - message.widget = view_item; handleNewUserMessage(message); } @@ -646,18 +661,21 @@ TimelineView::sendNextPendingMessage() using namespace mtx::events; PendingMessage &m = pending_msgs_.head(); + + log::main()->info("[{}] sending next queued message", m.txn_id); + + if (m.is_encrypted) { + // sendEncryptedMessage(m); + log::main()->info("[{}] sending encrypted event", m.txn_id); + return; + } + switch (m.ty) { case mtx::events::MessageType::Audio: { - msg::Audio audio; - audio.info.mimetype = m.mime.toStdString(); - audio.info.size = m.media_size; - audio.body = m.filename.toStdString(); - audio.url = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - audio, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -667,16 +685,10 @@ TimelineView::sendNextPendingMessage() break; } case mtx::events::MessageType::Image: { - msg::Image image; - image.info.mimetype = m.mime.toStdString(); - image.info.size = m.media_size; - image.body = m.filename.toStdString(); - image.url = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - image, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -686,16 +698,10 @@ TimelineView::sendNextPendingMessage() break; } case mtx::events::MessageType::Video: { - msg::Video video; - video.info.mimetype = m.mime.toStdString(); - video.info.size = m.media_size; - video.body = m.filename.toStdString(); - video.url = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - video, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -705,16 +711,10 @@ TimelineView::sendNextPendingMessage() break; } case mtx::events::MessageType::File: { - msg::File file; - file.info.mimetype = m.mime.toStdString(); - file.info.size = m.media_size; - file.body = m.filename.toStdString(); - file.url = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - file, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -724,13 +724,10 @@ TimelineView::sendNextPendingMessage() break; } case mtx::events::MessageType::Text: { - msg::Text text; - text.body = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - text, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -740,13 +737,10 @@ TimelineView::sendNextPendingMessage() break; } case mtx::events::MessageType::Emote: { - msg::Emote emote; - emote.body = m.body.toStdString(); - http::v2::client()->send_room_message( room_id_.toStdString(), m.txn_id, - emote, + toRoomMessage(m), std::bind(&TimelineView::sendRoomMessageHandler, this, m.txn_id, @@ -809,13 +803,15 @@ TimelineView::removePendingMessage(const std::string &txn_id) if (pending_sent_msgs_.isEmpty()) sendNextPendingMessage(); - return; + log::main()->info("[{}] removed message with sync", txn_id); } } for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); ++it) { if (it->txn_id == txn_id) { int index = std::distance(pending_msgs_.begin(), it); pending_msgs_.removeAt(index); + + log::main()->info("[{}] removed message before sync", txn_id); return; } } @@ -1051,9 +1047,80 @@ TimelineView::sendRoomMessageHandler(const std::string &txn_id, mtx::http::RequestErr err) { if (err) { + const int status_code = static_cast(err->status_code); + log::net()->warn("[{}] failed to send message: {} {}", + txn_id, + err->matrix_error.error, + status_code); emit messageFailed(txn_id); return; } emit messageSent(txn_id, QString::fromStdString(res.event_id.to_string())); } + +template<> +mtx::events::msg::Audio +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::Audio audio; + audio.info.mimetype = m.mime.toStdString(); + audio.info.size = m.media_size; + audio.body = m.filename.toStdString(); + audio.url = m.body.toStdString(); + return audio; +} + +template<> +mtx::events::msg::Image +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::Image image; + image.info.mimetype = m.mime.toStdString(); + image.info.size = m.media_size; + image.body = m.filename.toStdString(); + image.url = m.body.toStdString(); + return image; +} + +template<> +mtx::events::msg::Video +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::Video video; + video.info.mimetype = m.mime.toStdString(); + video.info.size = m.media_size; + video.body = m.filename.toStdString(); + video.url = m.body.toStdString(); + return video; +} + +template<> +mtx::events::msg::Emote +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::Emote emote; + emote.body = m.body.toStdString(); + return emote; +} + +template<> +mtx::events::msg::File +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::File file; + file.info.mimetype = m.mime.toStdString(); + file.info.size = m.media_size; + file.body = m.filename.toStdString(); + file.url = m.body.toStdString(); + return file; +} + +template<> +mtx::events::msg::Text +toRoomMessage(const PendingMessage &m) +{ + mtx::events::msg::Text text; + text.body = m.body.toStdString(); + return text; +} diff --git a/src/timeline/TimelineViewManager.cc b/src/timeline/TimelineViewManager.cc index 9026463d..b6e7d50d 100644 --- a/src/timeline/TimelineViewManager.cc +++ b/src/timeline/TimelineViewManager.cc @@ -22,8 +22,6 @@ #include #include -#include "MatrixClient.h" - #include "timeline/TimelineView.h" #include "timeline/TimelineViewManager.h" #include "timeline/widgets/AudioItem.h"