diff --git a/bin/dbus/cx.ring.Ring.ConfigurationManager.xml b/bin/dbus/cx.ring.Ring.ConfigurationManager.xml index 2de4955e3fe187706c243ecf54a4f4e0dcc7fc83..a992463dc66e20edefc2fd65f43c0885d0cc233c 100644 --- a/bin/dbus/cx.ring.Ring.ConfigurationManager.xml +++ b/bin/dbus/cx.ring.Ring.ConfigurationManager.xml @@ -542,6 +542,16 @@ </arg> </method> + <method name="cancelMessage" tp:name-for-bindings="cancelMessage"> + <arg type="s" name="accountID" direction="in"/> + <arg type="t" name="id" direction="in"/> + <arg type="b" name="success" direction="out"> + <tp:docstring> + Cancel pending message. + </tp:docstring> + </arg> + </method> + <method name="getLastMessages" tp:name-for-bindings="getLastMessages"> <arg type="s" name="accountID" direction="in"/> <arg type="t" name="base_timestamp" direction="in"/> diff --git a/bin/jni/configurationmanager.i b/bin/jni/configurationmanager.i index 0d5200f8b28cb40e63dbf42e91eabdd71bca1f82..08767ec252a0579a8d38d9b4c91cd53510533146 100644 --- a/bin/jni/configurationmanager.i +++ b/bin/jni/configurationmanager.i @@ -89,6 +89,8 @@ void registerAllAccounts(void); uint64_t sendAccountTextMessage(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& message); std::vector<DRing::Message> getLastMessages(const std::string& accountID, uint64_t base_timestamp); int getMessageStatus(uint64_t id); +int getMessageStatus(const std::string& accountID, uint64_t id); +bool cancelMessage(const std::string& accountID, uint64_t id); bool lookupName(const std::string& account, const std::string& nameserver, const std::string& name); bool lookupAddress(const std::string& account, const std::string& nameserver, const std::string& address); diff --git a/bin/nodejs/configurationmanager.i b/bin/nodejs/configurationmanager.i index 17deafcf1fd98c1f3f171a9aa9ecd73afe57b566..aee3d5e4a1c24678329b6240daccee18d03d79b6 100644 --- a/bin/nodejs/configurationmanager.i +++ b/bin/nodejs/configurationmanager.i @@ -85,6 +85,8 @@ void registerAllAccounts(void); uint64_t sendAccountTextMessage(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& message); std::vector<Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp); int getMessageStatus(uint64_t id); +int getMessageStatus(const std::string& accountID, uint64_t id); +bool cancelMessage(const std::string& accountID, uint64_t id); bool lookupName(const std::string& account, const std::string& nameserver, const std::string& name); bool lookupAddress(const std::string& account, const std::string& nameserver, const std::string& address); diff --git a/configure.ac b/configure.ac index fc7ec1326f1f1b6b3d38151c21815ce8bec58d15..599f604b31997216f1081be0b67a70726bc7eca7 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Jami - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([Jami Daemon],[7.5.0],[ring@gnu.org],[jami]) +AC_INIT([Jami Daemon],[7.6.0],[ring@gnu.org],[jami]) AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2019]]) AC_REVISION([$Revision$]) diff --git a/src/account.h b/src/account.h index 89d489712678ab6f3c6e5fb9e6cd00a8624d20f3..429bc542a648dd590f2e964190a1f10e590a62c4 100644 --- a/src/account.h +++ b/src/account.h @@ -163,10 +163,14 @@ class Account : public Serializable, public std::enable_shared_from_this<Account /** * Return the status corresponding to the token. */ - virtual im::MessageStatus getMessageStatus(uint64_t id UNUSED) const { + virtual im::MessageStatus getMessageStatus(uint64_t /*id*/) const { return im::MessageStatus::UNKNOWN; } + virtual bool cancelMessage(uint64_t /*id*/) { + return false; + } + std::vector<std::shared_ptr<Call>> getCalls(); /** diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp index d3bae8c0b3635eda15ac337261a4411f87aae844..77fd50d8898aa132726fe889d72543986a4fedb9 100644 --- a/src/client/configurationmanager.cpp +++ b/src/client/configurationmanager.cpp @@ -265,13 +265,29 @@ sendAccountTextMessage(const std::string& accountID, const std::string& to, cons std::vector<Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp) { - return ring::Manager::instance().getLastMessages(accountID, base_timestamp); + if (const auto acc = ring::Manager::instance().getAccount(accountID)) + return acc->getLastMessages(base_timestamp); + return {}; +} + +int +getMessageStatus(uint64_t messageId) +{ + return ring::Manager::instance().getMessageStatus(messageId); } int -getMessageStatus(uint64_t id) +getMessageStatus(const std::string& accountID, uint64_t messageId) { - return ring::Manager::instance().getMessageStatus(id); + return ring::Manager::instance().getMessageStatus(accountID, messageId); +} + +bool +cancelMessage(const std::string& accountID, uint64_t messageId) +{ + if (const auto acc = ring::Manager::instance().getAccount(accountID)) + return acc->cancelMessage(messageId); + return {}; } bool diff --git a/src/dring/account_const.h b/src/dring/account_const.h index 00925b77ac37903429079c3ac3854312ba58bbd4..4c9f9646b1d002ce03b7320a9b0951ed22aec703 100644 --- a/src/dring/account_const.h +++ b/src/dring/account_const.h @@ -67,7 +67,8 @@ enum class MessageStates : int { SENDING, SENT, READ, - FAILURE + FAILURE, + CANCELLED }; //DRing::Account::MessageStates enum class testAccountICEInitializationStatus : int { diff --git a/src/dring/configurationmanager_interface.h b/src/dring/configurationmanager_interface.h index 813b6dd0460608c6a2f7f11d4dc4ad0d1bc63dc5..e760b5ea486552769ebab263cfbd4400e1256433 100644 --- a/src/dring/configurationmanager_interface.h +++ b/src/dring/configurationmanager_interface.h @@ -75,9 +75,10 @@ DRING_PUBLIC std::vector<std::string> getAccountList(); DRING_PUBLIC void sendRegister(const std::string& accountID, bool enable); DRING_PUBLIC void registerAllAccounts(void); DRING_PUBLIC uint64_t sendAccountTextMessage(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& payloads); +DRING_PUBLIC bool cancelMessage(const std::string& accountID, uint64_t message); DRING_PUBLIC std::vector<Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp); DRING_PUBLIC int getMessageStatus(uint64_t id); - +DRING_PUBLIC int getMessageStatus(const std::string& accountID, uint64_t id); DRING_PUBLIC std::map<std::string, std::string> getTlsDefaultSettings(); diff --git a/src/im/message_engine.cpp b/src/im/message_engine.cpp index cd6236245154dda098c0580e46c74d40af4e12f1..a3661f754da73f71585354a007b0b320c35ab81c 100644 --- a/src/im/message_engine.cpp +++ b/src/im/message_engine.cpp @@ -116,6 +116,25 @@ MessageEngine::getStatus(MessageToken t) const return MessageStatus::UNKNOWN; } +bool +MessageEngine::cancel(MessageToken t) +{ + std::lock_guard<std::mutex> lock(messagesMutex_); + for (auto& p : messages_) { + auto m = p.second.find(t); + if (m != p.second.end()) { + m->second.status = MessageStatus::CANCELLED; + emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(account_.getAccountID(), + t, + m->second.to, + static_cast<int>(DRing::Account::MessageStates::CANCELLED)); + save_(); + return true; + } + } + return false; +} + void MessageEngine::onMessageSent(const std::string& peer, MessageToken token, bool ok) { @@ -215,7 +234,7 @@ MessageEngine::save_() const Json::Value peerRoot(Json::objectValue); for (auto& m : c.second) { auto& v = m.second; - if (v.status == MessageStatus::FAILURE || v.status == MessageStatus::SENT) + if (v.status == MessageStatus::FAILURE || v.status == MessageStatus::SENT || v.status == MessageStatus::CANCELLED) continue; Json::Value msg; std::ostringstream msgsId; diff --git a/src/im/message_engine.h b/src/im/message_engine.h index 353c5ad59a29c7ccb4cf0789cc134a4328189ada..c68bf0eb27927289aaff9c9559c5ea8f22b0408b 100644 --- a/src/im/message_engine.h +++ b/src/im/message_engine.h @@ -40,7 +40,8 @@ enum class MessageStatus { SENDING, SENT, READ, - FAILURE + FAILURE, + CANCELLED }; class MessageEngine @@ -53,6 +54,8 @@ public: MessageStatus getStatus(MessageToken t) const; + bool cancel(MessageToken t); + bool isSent(MessageToken t) const { return getStatus(t) == MessageStatus::SENT; } diff --git a/src/manager.cpp b/src/manager.cpp index 9344bba7f97937f455aa8e799990c85426d1dbad..84af6c6cd24466a25b125b8f94a7e99ecfac6c21 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -3027,30 +3027,42 @@ Manager::sendTextMessage(const std::string& accountID, const std::string& to, } int -Manager::getMessageStatus(uint64_t id) +statusFromImStatus(im::MessageStatus status) { + switch (status) { + case im::MessageStatus::IDLE: + case im::MessageStatus::SENDING: + return static_cast<int>(DRing::Account::MessageStates::SENDING); + case im::MessageStatus::SENT: + return static_cast<int>(DRing::Account::MessageStates::SENT); + case im::MessageStatus::READ: + return static_cast<int>(DRing::Account::MessageStates::READ); + case im::MessageStatus::FAILURE: + return static_cast<int>(DRing::Account::MessageStates::FAILURE); + default: + return static_cast<int>(DRing::Account::MessageStates::UNKNOWN); + } +} + +int +Manager::getMessageStatus(uint64_t id) const { const auto& allAccounts = accountFactory.getAllAccounts(); for (auto acc : allAccounts) { auto status = acc->getMessageStatus(id); - if (status != im::MessageStatus::UNKNOWN) { - switch (status) { - case im::MessageStatus::IDLE: - case im::MessageStatus::SENDING: - return static_cast<int>(DRing::Account::MessageStates::SENDING); - case im::MessageStatus::SENT: - return static_cast<int>(DRing::Account::MessageStates::SENT); - case im::MessageStatus::READ: - return static_cast<int>(DRing::Account::MessageStates::READ); - case im::MessageStatus::FAILURE: - return static_cast<int>(DRing::Account::MessageStates::FAILURE); - default: - return static_cast<int>(DRing::Account::MessageStates::UNKNOWN); - } - } + if (status != im::MessageStatus::UNKNOWN) + return statusFromImStatus(status); } return static_cast<int>(DRing::Account::MessageStates::UNKNOWN); } +int +Manager::getMessageStatus(const std::string& accountID, uint64_t id) const +{ + if (const auto acc = getAccount(accountID)) + return statusFromImStatus(acc->getMessageStatus(id)); + return static_cast<int>(DRing::Account::MessageStates::UNKNOWN); +} + void Manager::setAccountActive(const std::string& accountID, bool active) { diff --git a/src/manager.h b/src/manager.h index f50bf67c21ee353542a897eab5595c5d3c44d8c4..083d22eedf48c280f01cefd34a4b6dfbe5055066 100644 --- a/src/manager.h +++ b/src/manager.h @@ -388,7 +388,8 @@ class Manager { uint64_t sendTextMessage(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& payloads); - int getMessageStatus(uint64_t id); + int getMessageStatus(uint64_t id) const; + int getMessageStatus(const std::string& accountID, uint64_t id) const; /** * Get account list diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h index f822357986a6ae547c0884f6bcb8b410eedb7127..2ebcdbe8e080069526468c1868a5e1dcdae475c3 100644 --- a/src/sip/sipaccountbase.h +++ b/src/sip/sipaccountbase.h @@ -268,6 +268,10 @@ public: return messageEngine_.getStatus(id); } + virtual bool cancelMessage(uint64_t id) override { + return messageEngine_.cancel(id); + } + void onTextMessage(const std::string& from, const std::map<std::string, std::string>& payloads); /* Returns true if the username and/or hostname match this account */