mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 19:18:06 +00:00
Handle imdn namespace and Disposition-Notification header in CPIM.
This commit is contained in:
parent
f4f642a4d5
commit
d1dc223898
9 changed files with 210 additions and 34 deletions
|
|
@ -35,6 +35,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
|
|||
call/remote-conference-call.h
|
||||
chat/chat-message/chat-message-p.h
|
||||
chat/chat-message/chat-message.h
|
||||
chat/chat-message/notification-message.h
|
||||
chat/chat-room/abstract-chat-room-p.h
|
||||
chat/chat-room/abstract-chat-room.h
|
||||
chat/chat-room/basic-chat-room-p.h
|
||||
|
|
@ -190,6 +191,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES
|
|||
call/local-conference-call.cpp
|
||||
call/remote-conference-call.cpp
|
||||
chat/chat-message/chat-message.cpp
|
||||
chat/chat-message/notification-message.cpp
|
||||
chat/chat-room/abstract-chat-room.cpp
|
||||
chat/chat-room/basic-chat-room.cpp
|
||||
chat/chat-room/basic-to-client-group-chat-room.cpp
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class ChatMessagePrivate : public ObjectPrivate {
|
|||
friend class CpimChatMessageModifier;
|
||||
friend class EncryptionChatMessageModifier;
|
||||
friend class MultipartChatMessageModifier;
|
||||
friend class NotificationMessagePrivate;
|
||||
|
||||
public:
|
||||
enum Step {
|
||||
|
|
@ -99,6 +100,13 @@ public:
|
|||
SalOp *getSalOp () const;
|
||||
void setSalOp (SalOp *op);
|
||||
|
||||
bool getDisplayNotificationRequired () const { return displayNotificationRequired; }
|
||||
bool getNegativeDeliveryNotificationRequired () const { return negativeDeliveryNotificationRequired; }
|
||||
bool getPositiveDeliveryNotificationRequired () const { return positiveDeliveryNotificationRequired; }
|
||||
virtual void setDisplayNotificationRequired (bool value) { displayNotificationRequired = value; }
|
||||
virtual void setNegativeDeliveryNotificationRequired (bool value) { negativeDeliveryNotificationRequired = value; }
|
||||
virtual void setPositiveDeliveryNotificationRequired (bool value) { positiveDeliveryNotificationRequired = value; }
|
||||
|
||||
SalCustomHeader *getSalCustomHeaders () const;
|
||||
void setSalCustomHeaders (SalCustomHeader *headers);
|
||||
|
||||
|
|
@ -156,11 +164,20 @@ public:
|
|||
void updateInDb ();
|
||||
|
||||
private:
|
||||
|
||||
ChatMessagePrivate(const std::shared_ptr<AbstractChatRoom> &cr, ChatMessage::Direction dir);
|
||||
|
||||
|
||||
static bool validStateTransition (ChatMessage::State currentState, ChatMessage::State newState);
|
||||
|
||||
public:
|
||||
mutable MainDbChatMessageKey dbKey;
|
||||
|
||||
protected:
|
||||
bool displayNotificationRequired = true;
|
||||
bool negativeDeliveryNotificationRequired = true;
|
||||
bool positiveDeliveryNotificationRequired = true;
|
||||
bool toBeStored = true;
|
||||
|
||||
private:
|
||||
// TODO: Clean attributes.
|
||||
time_t time = ::ms_time(0); // TODO: Change me in all files.
|
||||
std::string imdnId;
|
||||
|
|
@ -189,10 +206,6 @@ private:
|
|||
// TODO: Remove my comment. VARIABLES OK.
|
||||
// Do not expose.
|
||||
|
||||
public:
|
||||
mutable MainDbChatMessageKey dbKey;
|
||||
|
||||
private:
|
||||
std::weak_ptr<AbstractChatRoom> chatRoom;
|
||||
ChatRoomId chatRoomId;
|
||||
IdentityAddress fromAddress;
|
||||
|
|
@ -204,7 +217,6 @@ private:
|
|||
std::list<Content* > contents;
|
||||
|
||||
bool encryptionPrevented = false;
|
||||
bool toBeStored = true;
|
||||
mutable bool contentsNotLoadedFromDatabase = false;
|
||||
L_DECLARE_PUBLIC(ChatMessage);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -457,7 +457,8 @@ void ChatMessagePrivate::setChatRoom (const shared_ptr<AbstractChatRoom> &cr) {
|
|||
void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) {
|
||||
L_Q();
|
||||
|
||||
shared_ptr<ChatMessage> msg = q->getChatRoom()->createChatMessage();
|
||||
auto chatRoomPrivate = static_cast<ChatRoomPrivate *>(q->getChatRoom()->getPrivate());
|
||||
shared_ptr<ChatMessage> msg = chatRoomPrivate->createNotificationMessage(ChatMessage::Direction::Outgoing);
|
||||
|
||||
Content *content = new Content();
|
||||
content->setContentDisposition(ContentDisposition::Notification);
|
||||
|
|
@ -468,7 +469,6 @@ void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) {
|
|||
if (reason != LinphoneReasonNone)
|
||||
msg->getPrivate()->setEncryptionPrevented(true);
|
||||
|
||||
msg->setToBeStored(false);
|
||||
msg->getPrivate()->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent);
|
||||
|
||||
msg->getPrivate()->send();
|
||||
|
|
@ -523,9 +523,8 @@ void ChatMessagePrivate::notifyReceiving () {
|
|||
// Legacy
|
||||
q->getChatRoom()->getPrivate()->notifyChatMessageReceived(q->getSharedFromThis());
|
||||
|
||||
if ((getContentType() != ContentType::Imdn) && (getContentType() != ContentType::ImIsComposing)) {
|
||||
if (getPositiveDeliveryNotificationRequired())
|
||||
q->sendDeliveryNotification(LinphoneReasonNone);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneReason ChatMessagePrivate::receive () {
|
||||
|
|
@ -894,7 +893,10 @@ bool ChatMessagePrivate::validStateTransition (ChatMessage::State currentState,
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
ChatMessage::ChatMessage (const shared_ptr<AbstractChatRoom> &chatRoom, ChatMessage::Direction direction) :
|
||||
Object(*new ChatMessagePrivate(chatRoom,direction)), CoreAccessor(chatRoom->getCore()) {
|
||||
Object(*new ChatMessagePrivate(chatRoom, direction)), CoreAccessor(chatRoom->getCore()) {
|
||||
}
|
||||
|
||||
ChatMessage::ChatMessage (ChatMessagePrivate &p) : Object(p), CoreAccessor(p.getPublic()->getChatRoom()->getCore()) {
|
||||
}
|
||||
|
||||
ChatMessage::~ChatMessage () {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public:
|
|||
L_DECLARE_ENUM(State, L_ENUM_VALUES_CHAT_MESSAGE_STATE);
|
||||
L_DECLARE_ENUM(Direction, L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION);
|
||||
|
||||
~ChatMessage ();
|
||||
virtual ~ChatMessage ();
|
||||
|
||||
// ----- TODO: Remove me.
|
||||
void cancelFileTransfer ();
|
||||
|
|
@ -93,7 +93,7 @@ public:
|
|||
bool isReadOnly () const;
|
||||
|
||||
bool getToBeStored () const;
|
||||
void setToBeStored (bool value);
|
||||
virtual void setToBeStored (bool value);
|
||||
|
||||
std::list<ParticipantImdnState> getParticipantsThatHaveDisplayed () const;
|
||||
std::list<ParticipantImdnState> getParticipantsThatHaveReceived () const;
|
||||
|
|
@ -114,6 +114,9 @@ public:
|
|||
bool downloadFile (FileTransferContent *content);
|
||||
bool isFileTransferInProgress();
|
||||
|
||||
protected:
|
||||
explicit ChatMessage (ChatMessagePrivate &p);
|
||||
|
||||
private:
|
||||
ChatMessage (const std::shared_ptr<AbstractChatRoom> &chatRoom, ChatMessage::Direction direction);
|
||||
|
||||
|
|
|
|||
55
src/chat/chat-message/notification-message.cpp
Normal file
55
src/chat/chat-message/notification-message.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* notification-message.cpp
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "chat/chat-message/chat-message-p.h"
|
||||
#include "chat/chat-message/notification-message.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class NotificationMessagePrivate : public ChatMessagePrivate {
|
||||
private:
|
||||
NotificationMessagePrivate(const std::shared_ptr<AbstractChatRoom> &cr, ChatMessage::Direction dir)
|
||||
: ChatMessagePrivate(cr, dir) {}
|
||||
|
||||
void setDisplayNotificationRequired (bool value) override {}
|
||||
void setNegativeDeliveryNotificationRequired (bool value) override {}
|
||||
void setPositiveDeliveryNotificationRequired (bool value) override {}
|
||||
|
||||
L_DECLARE_PUBLIC(NotificationMessage);
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
NotificationMessage::NotificationMessage (const shared_ptr<AbstractChatRoom> &chatRoom, ChatMessage::Direction direction) :
|
||||
ChatMessage(*new NotificationMessagePrivate(chatRoom, direction)) {
|
||||
L_D();
|
||||
d->displayNotificationRequired = false;
|
||||
d->negativeDeliveryNotificationRequired = false;
|
||||
d->positiveDeliveryNotificationRequired = false;
|
||||
d->toBeStored = false;
|
||||
}
|
||||
|
||||
void NotificationMessage::setToBeStored (bool value) {
|
||||
}
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
50
src/chat/chat-message/notification-message.h
Normal file
50
src/chat/chat-message/notification-message.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* notification-message.h
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _L_NOTIFICATION_MESSAGE_H_
|
||||
#define _L_NOTIFICATION_MESSAGE_H_
|
||||
|
||||
#include "chat/chat-message/chat-message.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
class NotificationMessagePrivate;
|
||||
|
||||
class LINPHONE_PUBLIC NotificationMessage : public ChatMessage {
|
||||
public:
|
||||
friend class ChatRoomPrivate;
|
||||
|
||||
L_OVERRIDE_SHARED_FROM_THIS(NotificationMessage);
|
||||
|
||||
virtual ~NotificationMessage () = default;
|
||||
|
||||
void setToBeStored (bool value) override;
|
||||
|
||||
private:
|
||||
NotificationMessage (const std::shared_ptr<AbstractChatRoom> &chatRoom, ChatMessage::Direction direction);
|
||||
|
||||
L_DECLARE_PRIVATE(NotificationMessage);
|
||||
L_DISABLE_COPY(NotificationMessage);
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _L_NOTIFICATION_MESSAGE_H_
|
||||
|
|
@ -54,6 +54,7 @@ public:
|
|||
void removeTransientEvent (const std::shared_ptr<EventLog> &eventLog) override;
|
||||
|
||||
std::shared_ptr<ChatMessage> createChatMessage (ChatMessage::Direction direction);
|
||||
std::shared_ptr<ChatMessage> createNotificationMessage (ChatMessage::Direction direction);
|
||||
std::list<std::shared_ptr<ChatMessage>> findChatMessages (const std::string &messageId) const;
|
||||
|
||||
void notifyChatMessageReceived (const std::shared_ptr<ChatMessage> &chatMessage) override;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "chat/chat-message/chat-message-p.h"
|
||||
#include "chat/chat-message/notification-message.h"
|
||||
#include "chat/chat-room/chat-room-p.h"
|
||||
#include "core/core-p.h"
|
||||
#include "sip-tools/sip-headers.h"
|
||||
|
|
@ -84,8 +85,7 @@ void ChatRoomPrivate::sendIsComposingNotification () {
|
|||
content->setContentType(ContentType::ImIsComposing);
|
||||
content->setBody(payload);
|
||||
|
||||
shared_ptr<ChatMessage> chatMessage = createChatMessage(ChatMessage::Direction::Outgoing);
|
||||
chatMessage->setToBeStored(false);
|
||||
shared_ptr<ChatMessage> chatMessage = createNotificationMessage(ChatMessage::Direction::Outgoing);
|
||||
chatMessage->addContent(content);
|
||||
chatMessage->getPrivate()->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent);
|
||||
chatMessage->getPrivate()->addSalCustomHeader("Expires", "0");
|
||||
|
|
@ -121,6 +121,11 @@ shared_ptr<ChatMessage> ChatRoomPrivate::createChatMessage (ChatMessage::Directi
|
|||
return shared_ptr<ChatMessage>(new ChatMessage(q->getSharedFromThis(), direction));
|
||||
}
|
||||
|
||||
shared_ptr<ChatMessage> ChatRoomPrivate::createNotificationMessage (ChatMessage::Direction direction) {
|
||||
L_Q();
|
||||
return shared_ptr<ChatMessage>(new NotificationMessage(q->getSharedFromThis(), direction));
|
||||
}
|
||||
|
||||
list<shared_ptr<ChatMessage>> ChatRoomPrivate::findChatMessages (const string &messageId) const {
|
||||
L_Q();
|
||||
return q->getCore()->getPrivate()->mainDb->findChatMessages(q->getChatRoomId(), messageId);
|
||||
|
|
@ -214,26 +219,21 @@ LinphoneReason ChatRoomPrivate::onSipMessageReceived (SalOp *op, const SalMessag
|
|||
reason = msg->getPrivate()->receive();
|
||||
|
||||
if (reason == LinphoneReasonNotAcceptable || reason == LinphoneReasonUnknown) {
|
||||
/* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */
|
||||
reason = LinphoneReasonNone;
|
||||
goto end;
|
||||
// Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt
|
||||
return LinphoneReasonNone;
|
||||
}
|
||||
|
||||
if (msg->getPrivate()->getContentType() == ContentType::ImIsComposing) {
|
||||
onIsComposingReceived(msg->getFromAddress(), msg->getPrivate()->getText());
|
||||
if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1)
|
||||
return reason;
|
||||
} else if (msg->getPrivate()->getContentType() == ContentType::Imdn) {
|
||||
onImdnReceived(msg);
|
||||
if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1) {
|
||||
goto end;
|
||||
}
|
||||
if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1)
|
||||
return reason;
|
||||
}
|
||||
|
||||
onChatMessageReceived(msg);
|
||||
|
||||
end:
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "linphone/utils/utils.h"
|
||||
|
||||
#include "address/address.h"
|
||||
#include "chat/chat-message/chat-message-p.h"
|
||||
#include "chat/cpim/cpim.h"
|
||||
|
|
@ -42,12 +44,33 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr<Ch
|
|||
Cpim::ToHeader cpimToHeader;
|
||||
cpimToHeader.setValue(cpimAddressAsString(message->getToAddress()));
|
||||
cpimMessage.addMessageHeader(cpimToHeader);
|
||||
char token[13];
|
||||
belle_sip_random_token(token, sizeof(token));
|
||||
Cpim::MessageIdHeader cpimMessageIdHeader;
|
||||
cpimMessageIdHeader.setValue(token);
|
||||
cpimMessage.addMessageHeader(cpimMessageIdHeader);
|
||||
message->getPrivate()->setImdnMessageId(token);
|
||||
|
||||
if (message->getPrivate()->getPositiveDeliveryNotificationRequired()
|
||||
|| message->getPrivate()->getDisplayNotificationRequired()
|
||||
) {
|
||||
const string imdnNamespace = "imdn";
|
||||
Cpim::NsHeader cpimNsHeader;
|
||||
cpimNsHeader.setValue(imdnNamespace + " <urn:ietf:params:imdn>");
|
||||
cpimMessage.addMessageHeader(cpimNsHeader);
|
||||
|
||||
char token[13];
|
||||
belle_sip_random_token(token, sizeof(token));
|
||||
Cpim::GenericHeader cpimMessageIdHeader;
|
||||
cpimMessageIdHeader.setName("Message-ID"); // TODO: Replace by imdnNamespace + ".Message-ID");
|
||||
cpimMessageIdHeader.setValue(token);
|
||||
cpimMessage.addMessageHeader(cpimMessageIdHeader);
|
||||
message->getPrivate()->setImdnMessageId(token);
|
||||
|
||||
Cpim::GenericHeader dispositionNotificationHeader;
|
||||
dispositionNotificationHeader.setName(imdnNamespace + ".Disposition-Notification");
|
||||
vector<string> dispositionNotificationValues;
|
||||
if (message->getPrivate()->getPositiveDeliveryNotificationRequired())
|
||||
dispositionNotificationValues.emplace_back("positive-delivery");
|
||||
if (message->getPrivate()->getDisplayNotificationRequired())
|
||||
dispositionNotificationValues.emplace_back("display");
|
||||
dispositionNotificationHeader.setValue(Utils::join(dispositionNotificationValues, ", "));
|
||||
cpimMessage.addMessageHeader(dispositionNotificationHeader);
|
||||
}
|
||||
|
||||
const Content *content;
|
||||
if (!message->getInternalContent().isEmpty()) {
|
||||
|
|
@ -125,17 +148,45 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptr<Ch
|
|||
}
|
||||
newContent.setBody(cpimMessage->getContent());
|
||||
|
||||
message->getPrivate()->setPositiveDeliveryNotificationRequired(false);
|
||||
message->getPrivate()->setNegativeDeliveryNotificationRequired(false);
|
||||
message->getPrivate()->setDisplayNotificationRequired(false);
|
||||
|
||||
Address cpimFromAddress;
|
||||
Address cpimToAddress;
|
||||
l = cpimMessage->getMessageHeaders();
|
||||
if (l) {
|
||||
string imdnNamespace = "";
|
||||
for (const auto &header : *l.get()) {
|
||||
if (header->getName() == "NS") {
|
||||
string val = header->getValue();
|
||||
size_t startPos = 0;
|
||||
startPos = val.find("<", startPos);
|
||||
if (startPos == string::npos)
|
||||
break;
|
||||
size_t endPos = 0;
|
||||
endPos = val.find(">", startPos);
|
||||
if (endPos == string::npos)
|
||||
break;
|
||||
if (val.substr(startPos, endPos) == "<urn:ietf:params:imdn>")
|
||||
imdnNamespace = Utils::trim(val.substr(0, startPos));
|
||||
}
|
||||
}
|
||||
for (const auto &header : *l.get()) {
|
||||
if (header->getName() == "From")
|
||||
cpimFromAddress = Address(header->getValue());
|
||||
else if (header->getName() == "To")
|
||||
cpimToAddress = Address(header->getValue());
|
||||
else if (header->getName() == "Message-ID")
|
||||
else if ((header->getName() == "Message-ID") || (header->getName() == (imdnNamespace + ".Message-ID")))
|
||||
message->getPrivate()->setImdnMessageId(header->getValue());
|
||||
else if ((header->getName() == (imdnNamespace + ".Disposition-Notification"))) {
|
||||
vector<string> values = Utils::split(header->getValue(), ", ");
|
||||
for (const auto &value : values)
|
||||
if (value == "positive-delivery")
|
||||
message->getPrivate()->setPositiveDeliveryNotificationRequired(true);
|
||||
else if (value == "display")
|
||||
message->getPrivate()->setDisplayNotificationRequired(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue