From 50cc85d3dea93735fe352831421eea2fcf9c24c5 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 4 Oct 2018 14:41:48 +0900 Subject: Modernise and fix code dealing with call events Call events no more store deserialised values; instead they deserialise values on the fly, same as all other events. They are no more treated as state events (The Spec doesn't define them as state events in the first place). A common base class, CallEventBase, is introduced that defines data pieces common to all call events (call id and version). --- lib/eventitem.h | 7 +++++ lib/events/callanswerevent.cpp | 32 +++++++++----------- lib/events/callanswerevent.h | 33 +++----------------- lib/events/callcandidatesevent.cpp | 27 ----------------- lib/events/callcandidatesevent.h | 31 ++++++------------- lib/events/callhangupevent.cpp | 11 ++----- lib/events/callhangupevent.h | 20 +----------- lib/events/callinviteevent.cpp | 20 +++++------- lib/events/callinviteevent.h | 41 ++++++------------------- lib/events/event.h | 17 +++++++++-- lib/events/roomevent.cpp | 22 ++++++++++++++ lib/events/roomevent.h | 14 +++++++++ lib/room.cpp | 62 ++++++++++++-------------------------- lib/room.h | 6 ++-- 14 files changed, 129 insertions(+), 214 deletions(-) (limited to 'lib') diff --git a/lib/eventitem.h b/lib/eventitem.h index 6bec5a7f..5f1d10c9 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -98,6 +98,13 @@ namespace QMatrixClient : nullptr; } + template<> + inline const CallEventBase* EventItemBase::viewAs() const + { + return evt->isCallEvent() ? weakPtrCast(evt) + : nullptr; + } + class PendingEventItem : public EventItemBase { Q_GADGET diff --git a/lib/events/callanswerevent.cpp b/lib/events/callanswerevent.cpp index c28ad305..d2862241 100644 --- a/lib/events/callanswerevent.cpp +++ b/lib/events/callanswerevent.cpp @@ -48,29 +48,25 @@ m.call.answer using namespace QMatrixClient; CallAnswerEvent::CallAnswerEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - , _lifetime(contentJson()["lifetime"].toInt()) - , _sdp(contentJson()["answer"].toObject()["sdp"].toString()) - , _callId(contentJson()["call_id"].toString()) - , _version(contentJson()["version"].toInt()) + : CallEventBase(typeId(), obj) { qCDebug(EVENTS) << "Call Answer event"; } CallAnswerEvent::CallAnswerEvent(const QString& callId, const int lifetime, const QString& sdp) - : RoomEvent(typeId(), NULL) -{ - _version = 0; - _callId = callId; - _lifetime = lifetime; - _sdp = sdp; -} + : CallEventBase(typeId(), matrixTypeId(), callId, 0, + { { QStringLiteral("lifetime"), lifetime } + , { QStringLiteral("answer"), QJsonObject { + { QStringLiteral("type"), QStringLiteral("answer") }, + { QStringLiteral("sdp"), sdp } } } + }) +{ } CallAnswerEvent::CallAnswerEvent(const QString& callId, const QString& sdp) - : RoomEvent(typeId(), NULL) -{ - _version = 0; - _callId = callId; - _sdp = sdp; -} + : CallEventBase(typeId(), matrixTypeId(), callId, 0, + { { QStringLiteral("answer"), QJsonObject { + { QStringLiteral("type"), QStringLiteral("answer") }, + { QStringLiteral("sdp"), sdp } } } + }) +{ } diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h index b5b47899..2d9e5bb0 100644 --- a/lib/events/callanswerevent.h +++ b/lib/events/callanswerevent.h @@ -22,7 +22,7 @@ namespace QMatrixClient { - class CallAnswerEvent: public RoomEvent + class CallAnswerEvent: public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.answer", CallAnswerEvent) @@ -33,34 +33,11 @@ namespace QMatrixClient const QString& sdp); explicit CallAnswerEvent(const QString& callId, const QString& sdp); - bool isStateEvent() const override { return true; } - - const int lifetime() const { return _lifetime; } - const QString& sdp() const { return _sdp; } - const QString& callId() const { return _callId; } - const int version() const { return _version; } - - QJsonObject toJson() const - { - QJsonObject answer; - answer.insert("sdp", _sdp); - answer.insert("type", QStringLiteral("answer")); - - QJsonObject obj; - obj.insert("call_id", _callId); - obj.insert("version", _version); - if (_lifetime != NULL) - obj.insert("lifetime", _lifetime); - obj.insert("answer", answer); - return obj; + int lifetime() const { return content("lifetime"_ls); } // FIXME: Omittable<>? + QString sdp() const { + return contentJson()["answer"_ls].toObject() + .value("sdp"_ls).toString(); } - - private: - int _lifetime; - QJsonObject _answer; - QString _sdp; - QString _callId; - int _version; }; REGISTER_EVENT_TYPE(CallAnswerEvent) diff --git a/lib/events/callcandidatesevent.cpp b/lib/events/callcandidatesevent.cpp index 40d9ce05..52cd1856 100644 --- a/lib/events/callcandidatesevent.cpp +++ b/lib/events/callcandidatesevent.cpp @@ -18,12 +18,6 @@ #include "callcandidatesevent.h" -#include "event.h" - -#include "logging.h" - -#include - /* m.call.candidates { @@ -46,24 +40,3 @@ m.call.candidates "type": "m.call.candidates" } */ - -using namespace QMatrixClient; - - -CallCandidatesEvent::CallCandidatesEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - , _candidates(contentJson()["candidates"].toArray()) - , _callId(contentJson()["call_id"].toString()) - , _version(contentJson()["version"].toInt()) -{ - qCDebug(EVENTS) << "Call Candidates event"; -} - -CallCandidatesEvent::CallCandidatesEvent(const QString& callId, - const QJsonArray& candidates) - : RoomEvent(typeId(), NULL) -{ - _version = 0; - _callId = callId; - _candidates = candidates; -} diff --git a/lib/events/callcandidatesevent.h b/lib/events/callcandidatesevent.h index 8e66499d..4618832c 100644 --- a/lib/events/callcandidatesevent.h +++ b/lib/events/callcandidatesevent.h @@ -19,39 +19,28 @@ #pragma once #include "roomevent.h" -#include namespace QMatrixClient { - class CallCandidatesEvent: public RoomEvent + class CallCandidatesEvent: public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.candidates", CallCandidatesEvent) - explicit CallCandidatesEvent(const QJsonObject& obj); + explicit CallCandidatesEvent(const QJsonObject& obj) + : CallEventBase(typeId(), obj) + { } explicit CallCandidatesEvent(const QString& callId, - const QJsonArray& candidates); + const QJsonArray& candidates) + : CallEventBase(typeId(), matrixTypeId(), callId, 0, + {{ QStringLiteral("candidates"), candidates }}) + { } - bool isStateEvent() const override { return true; } - - const QJsonArray& candidates() const { return _candidates; } - const QString& callId() const { return _callId; } - const int version() const { return _version; } - - QJsonObject toJson() const + QJsonArray candidates() const { - QJsonObject obj; - obj.insert("call_id", _callId); - obj.insert("version", _version); - obj.insert("candidates", _candidates); - return obj; + return content("candidates"_ls); } - - private: - QJsonArray _candidates; - QString _callId; - int _version; }; REGISTER_EVENT_TYPE(CallCandidatesEvent) diff --git a/lib/events/callhangupevent.cpp b/lib/events/callhangupevent.cpp index 27f41a5f..b1154806 100644 --- a/lib/events/callhangupevent.cpp +++ b/lib/events/callhangupevent.cpp @@ -44,16 +44,11 @@ using namespace QMatrixClient; CallHangupEvent::CallHangupEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - , _callId(contentJson()["call_id"].toString()) - , _version(contentJson()["version"].toInt()) + : CallEventBase(typeId(), obj) { qCDebug(EVENTS) << "Call Hangup event"; } CallHangupEvent::CallHangupEvent(const QString& callId) - : RoomEvent(typeId(), NULL) -{ - _version = 0; - _callId = callId; -} + : CallEventBase(typeId(), matrixTypeId(), callId, 0) +{ } diff --git a/lib/events/callhangupevent.h b/lib/events/callhangupevent.h index 57e565a6..c74e20d5 100644 --- a/lib/events/callhangupevent.h +++ b/lib/events/callhangupevent.h @@ -22,31 +22,13 @@ namespace QMatrixClient { - class CallHangupEvent: public RoomEvent + class CallHangupEvent: public CallEventBase { public: DEFINE_EVENT_TYPEID("m.call.hangup", CallHangupEvent) explicit CallHangupEvent(const QJsonObject& obj); - explicit CallHangupEvent(const QString& callId); - - bool isStateEvent() const override { return true; } - - const QString& callId() const { return _callId; } - const int version() const { return _version; } - - QJsonObject toJson() const - { - QJsonObject obj; - obj.insert("call_id", _callId); - obj.insert("version", _version); - return obj; - } - - private: - QString _callId; - int _version; }; REGISTER_EVENT_TYPE(CallHangupEvent) diff --git a/lib/events/callinviteevent.cpp b/lib/events/callinviteevent.cpp index 71c49d66..bca3f296 100644 --- a/lib/events/callinviteevent.cpp +++ b/lib/events/callinviteevent.cpp @@ -48,21 +48,17 @@ m.call.invite using namespace QMatrixClient; CallInviteEvent::CallInviteEvent(const QJsonObject& obj) - : RoomEvent(typeId(), obj) - , _lifetime(contentJson()["lifetime"].toInt()) - , _sdp(contentJson()["offer"].toObject()["sdp"].toString()) - , _callId(contentJson()["call_id"].toString()) - , _version(contentJson()["version"].toInt()) + : CallEventBase(typeId(), obj) { qCDebug(EVENTS) << "Call Invite event"; } CallInviteEvent::CallInviteEvent(const QString& callId, const int lifetime, const QString& sdp) - : RoomEvent(typeId(), NULL) -{ - _version = 0; - _callId = callId; - _lifetime = lifetime; - _sdp = sdp; -} + : CallEventBase(typeId(), matrixTypeId(), callId, lifetime, + { { QStringLiteral("lifetime"), lifetime } + , { QStringLiteral("offer"), QJsonObject { + { QStringLiteral("type"), QStringLiteral("offer") }, + { QStringLiteral("sdp"), sdp } } + }}) +{ } diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h index 029b2e3d..d5315309 100644 --- a/lib/events/callinviteevent.h +++ b/lib/events/callinviteevent.h @@ -22,42 +22,21 @@ namespace QMatrixClient { - class CallInviteEvent: public RoomEvent + class CallInviteEvent: public CallEventBase { public: - DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent) + DEFINE_EVENT_TYPEID("m.call.invite", CallInviteEvent) - explicit CallInviteEvent(const QJsonObject& obj); + explicit CallInviteEvent(const QJsonObject& obj); - explicit CallInviteEvent(const QString& callId, const int lifetime, - const QString& sdp); + explicit CallInviteEvent(const QString& callId, const int lifetime, + const QString& sdp); - bool isStateEvent() const override { return true; } - - const int lifetime() const { return _lifetime; } - const QString& sdp() const { return _sdp; } - const QString& callId() const { return _callId; } - const int version() const { return _version; } - - QJsonObject toJson() const - { - QJsonObject offer; - offer.insert("sdp", _sdp); - offer.insert("type", QStringLiteral("offer")); - - QJsonObject obj; - obj.insert("call_id", _callId); - obj.insert("version", _version); - obj.insert("lifetime", _lifetime); - obj.insert("offer", offer); - return obj; - } - - private: - int _lifetime; - QString _sdp; - QString _callId; - int _version; + int lifetime() const { return content("lifetime"_ls); } // FIXME: Omittable<>? + QString sdp() const { + return contentJson()["offer"_ls].toObject() + .value("sdp"_ls).toString(); + } }; REGISTER_EVENT_TYPE(CallInviteEvent) diff --git a/lib/events/event.h b/lib/events/event.h index 9ba4b85a..cd23a818 100644 --- a/lib/events/event.h +++ b/lib/events/event.h @@ -18,11 +18,9 @@ #pragma once -#include "util.h" +#include "converters.h" #include "logging.h" -#include - #ifndef DISABLE_EVENTTYPE #define USE_EVENTTYPE 1 #endif @@ -247,7 +245,20 @@ namespace QMatrixClient const QJsonObject contentJson() const; const QJsonObject unsignedJson() const; + template + T content(const QString& key) const + { + return fromJson(contentJson()[key]); + } + + template + T content(const QLatin1String& key) const + { + return fromJson(contentJson()[key]); + } + virtual bool isStateEvent() const { return false; } + virtual bool isCallEvent() const { return false; } protected: QJsonObject& editJson() { return _json; } diff --git a/lib/events/roomevent.cpp b/lib/events/roomevent.cpp index e9d74cf6..80d121de 100644 --- a/lib/events/roomevent.cpp +++ b/lib/events/roomevent.cpp @@ -101,3 +101,25 @@ void RoomEvent::addId(const QString& newId) qCDebug(EVENTS) << "Event txnId -> id:" << transactionId() << "->" << id(); Q_ASSERT(id() == newId); } + +QJsonObject makeCallContentJson(const QString& callId, int version, + QJsonObject content) +{ + content.insert(QStringLiteral("call_id"), callId); + content.insert(QStringLiteral("version"), version); + return content; +} + +CallEventBase::CallEventBase(Type type, event_mtype_t matrixType, + const QString& callId, int version, + const QJsonObject& contentJson) + : RoomEvent(type, matrixType, + makeCallContentJson(callId, version, contentJson)) +{ } + +CallEventBase::CallEventBase(Event::Type type, const QJsonObject& json) + : RoomEvent(type, json) +{ + if (callId().isEmpty()) + qCWarning(EVENTS) << id() << "is a call event with an empty call id"; +} diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index f057753f..ce96174e 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -87,6 +87,20 @@ namespace QMatrixClient using RoomEventPtr = event_ptr_tt; using RoomEvents = EventsArray; using RoomEventsRange = Range; + + class CallEventBase: public RoomEvent + { + public: + CallEventBase(Type type, event_mtype_t matrixType, + const QString& callId, int version, + const QJsonObject& contentJson = {}); + CallEventBase(Type type, const QJsonObject& json); + ~CallEventBase() override = default; + bool isCallEvent() const override { return true; } + + QString callId() const { return content("call_id"_ls); } + int version() const { return content("version"_ls); } + }; } // namespace QMatrixClient Q_DECLARE_METATYPE(QMatrixClient::RoomEvent*) Q_DECLARE_METATYPE(const QMatrixClient::RoomEvent*) diff --git a/lib/room.cpp b/lib/room.cpp index ee2e2b8e..2253c636 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1300,58 +1300,42 @@ bool isEchoEvent(const RoomEventPtr& le, const PendingEventItem& re) return le->contentJson() == re->contentJson(); } -bool Room::processCall(Room* room, const RoomEvent* event) -{ - if (!room->isCallSupported()) { - qCDebug(MAIN) << "Got call event in room with more then two" - << "members, Ignoring this event!"; - return false; - } - emit callEvent(room, event); - return false; -} - -bool Room::isCallSupported() const +bool Room::supportsCalls() const { return d->membersMap.size() == 2; } void Room::inviteCall(const QString& callId, const int lifetime, - const QString& sdp) + const QString& sdp) { - Q_ASSERT(isCallSupported()); - auto *evt = new CallInviteEvent(callId, lifetime, sdp); - postEvent(evt); + Q_ASSERT(supportsCalls()); + postEvent(new CallInviteEvent(callId, lifetime, sdp)); } -void Room::callCandidates(const QString& callId, - const QJsonArray& candidates) +void Room::sendCallCandidates(const QString& callId, + const QJsonArray& candidates) { - Q_ASSERT(isCallSupported()); - auto *evt = new CallCandidatesEvent(callId, candidates); - postEvent(evt); + Q_ASSERT(supportsCalls()); + postEvent(new CallCandidatesEvent(callId, candidates)); } void Room::answerCall(const QString& callId, const int lifetime, - const QString& sdp) + const QString& sdp) { - Q_ASSERT(isCallSupported()); - auto *evt = new CallAnswerEvent(callId, lifetime, sdp); - postEvent(evt); + Q_ASSERT(supportsCalls()); + postEvent(new CallAnswerEvent(callId, lifetime, sdp)); } void Room::answerCall(const QString& callId, const QString& sdp) { - Q_ASSERT(isCallSupported()); - auto *evt = new CallAnswerEvent(callId, sdp); - postEvent(evt); + Q_ASSERT(supportsCalls()); + postEvent(new CallAnswerEvent(callId, sdp)); } void Room::hangupCall(const QString& callId) { - Q_ASSERT(isCallSupported()); - auto *evt = new CallHangupEvent(callId); - postEvent(evt); + Q_ASSERT(supportsCalls()); + postEvent(new CallHangupEvent(callId)); } void Room::getPreviousContent(int limit) @@ -1701,6 +1685,10 @@ void Room::Private::addNewMessageEvents(RoomEvents&& events) } emit q->pendingEventMerged(); } + if (q->supportsCalls()) + for (const auto& evt: RoomEventsRange(events.begin(), newEnd)) + if (evt->isCallEvent()) + emit q->callEvent(q, weakPtrCast(evt)); if (totalInserted > 0) { @@ -1829,18 +1817,6 @@ bool Room::processStateEvent(const RoomEvent& e) } return false; } - , [this] (const CallAnswerEvent& evt) { - return processCall(this, &evt); - } - , [this] (const CallCandidatesEvent& evt) { - return processCall(this, &evt); - } - , [this] (const CallHangupEvent& evt) { - return processCall(this, &evt); - } - , [this] (const CallInviteEvent& evt) { - return processCall(this, &evt); - } , [this] (const EncryptionEvent& evt) { d->encryptionAlgorithm = evt.algorithm(); qCDebug(MAIN) << "Encryption switched on in room" << id() diff --git a/lib/room.h b/lib/room.h index b81af69e..5ad8b2cf 100644 --- a/lib/room.h +++ b/lib/room.h @@ -305,14 +305,14 @@ namespace QMatrixClient Q_INVOKABLE void inviteCall(const QString& callId, const int lifetime, const QString& sdp); - Q_INVOKABLE void callCandidates(const QString& callId, + Q_INVOKABLE void sendCallCandidates(const QString& callId, const QJsonArray& candidates); Q_INVOKABLE void answerCall(const QString& callId, const int lifetime, const QString& sdp); Q_INVOKABLE void answerCall(const QString& callId, const QString& sdp); Q_INVOKABLE void hangupCall(const QString& callId); - Q_INVOKABLE bool isCallSupported() const; + Q_INVOKABLE bool supportsCalls() const; public slots: QString postMessage(const QString& plainText, MessageEventType type); @@ -437,8 +437,6 @@ namespace QMatrixClient const RoomEvent& /*after*/) { } private: - bool processCall(Room* room, const RoomEvent* event); - class Private; Private* d; }; -- cgit v1.2.3