mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 20:46:28 +00:00
Handle one-to-one chat rooms and quit the client group chat room when deleting it.
This commit is contained in:
parent
1e350eda33
commit
359b7bde4b
31 changed files with 390 additions and 93 deletions
|
|
@ -80,11 +80,30 @@ static void call_received(SalCallOp *h) {
|
||||||
LinphoneAddress *toAddr = linphone_address_new(h->get_to());
|
LinphoneAddress *toAddr = linphone_address_new(h->get_to());
|
||||||
|
|
||||||
if (_linphone_core_is_conference_creation(lc, toAddr)) {
|
if (_linphone_core_is_conference_creation(lc, toAddr)) {
|
||||||
if (sal_address_has_param(h->get_remote_contact_address(), "text"))
|
|
||||||
_linphone_core_create_server_group_chat_room(lc, h);
|
|
||||||
// TODO: handle media conference creation if the "text" feature tag is not present
|
|
||||||
linphone_address_unref(toAddr);
|
linphone_address_unref(toAddr);
|
||||||
linphone_address_unref(fromAddr);
|
linphone_address_unref(fromAddr);
|
||||||
|
if (sal_address_has_param(h->get_remote_contact_address(), "text")) {
|
||||||
|
bool oneToOneChatRoom = false;
|
||||||
|
const char *oneToOneChatRoomStr = sal_custom_header_find(h->get_recv_custom_header(), "One-To-One-Chat-Room");
|
||||||
|
if (oneToOneChatRoomStr && (strcmp(oneToOneChatRoomStr, "true") == 0))
|
||||||
|
oneToOneChatRoom = true;
|
||||||
|
if (oneToOneChatRoom) {
|
||||||
|
IdentityAddress from(h->get_from());
|
||||||
|
list<IdentityAddress> identAddresses = ServerGroupChatRoom::parseResourceLists(h->get_remote_body());
|
||||||
|
if (identAddresses.size() != 1) {
|
||||||
|
h->decline(SalReasonNotAcceptable, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IdentityAddress confAddr = L_GET_PRIVATE_FROM_C_OBJECT(lc)->mainDb->findOneToOneConferenceChatRoomAddress(from, identAddresses.front());
|
||||||
|
if (confAddr.isValid()) {
|
||||||
|
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(ChatRoomId(confAddr, confAddr));
|
||||||
|
L_GET_PRIVATE(static_pointer_cast<ServerGroupChatRoom>(chatRoom))->confirmRecreation(h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_linphone_core_create_server_group_chat_room(lc, h);
|
||||||
|
}
|
||||||
|
// TODO: handle media conference creation if the "text" feature tag is not present
|
||||||
return;
|
return;
|
||||||
} else if (sal_address_has_param(h->get_remote_contact_address(), "text")) {
|
} else if (sal_address_has_param(h->get_remote_contact_address(), "text")) {
|
||||||
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(
|
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc
|
||||||
}
|
}
|
||||||
|
|
||||||
void linphone_core_delete_chat_room (LinphoneCore *, LinphoneChatRoom *cr) {
|
void linphone_core_delete_chat_room (LinphoneCore *, LinphoneChatRoom *cr) {
|
||||||
LinphonePrivate::Core::deleteChatRoom(L_GET_CPP_PTR_FROM_C_OBJECT(cr));
|
L_GET_CPP_PTR_FROM_C_OBJECT(cr)->deleteFromDb();
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) {
|
LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) {
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,15 @@
|
||||||
F(Created) \
|
F(Created) \
|
||||||
F(TerminationPending) \
|
F(TerminationPending) \
|
||||||
F(Terminated) \
|
F(Terminated) \
|
||||||
F(CreationFailed)
|
F(CreationFailed) \
|
||||||
|
F(Deleted)
|
||||||
|
|
||||||
#define L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES(F) \
|
#define L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES(F) \
|
||||||
F(Basic, 1 << 0) \
|
F(Basic, 1 << 0) \
|
||||||
F(RealTimeText, 1 << 1) \
|
F(RealTimeText, 1 << 1) \
|
||||||
F(Conference, 1 << 2) \
|
F(Conference, 1 << 2) \
|
||||||
F(Proxy, 1 << 3) \
|
F(Proxy, 1 << 3) \
|
||||||
F(Migratable, 1 << 4)
|
F(Migratable, 1 << 4) \
|
||||||
|
F(OneToOne, 1 << 5)
|
||||||
|
|
||||||
#endif // ifndef _L_CHAT_ROOM_ENUMS_H_
|
#endif // ifndef _L_CHAT_ROOM_ENUMS_H_
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class LINPHONE_PUBLIC AbstractChatRoom : public Object, public CoreAccessor, pub
|
||||||
friend class ChatMessage;
|
friend class ChatMessage;
|
||||||
friend class ChatMessagePrivate;
|
friend class ChatMessagePrivate;
|
||||||
friend class ClientGroupToBasicChatRoomPrivate;
|
friend class ClientGroupToBasicChatRoomPrivate;
|
||||||
|
friend class Core;
|
||||||
friend class CorePrivate;
|
friend class CorePrivate;
|
||||||
friend class MainDb;
|
friend class MainDb;
|
||||||
friend class ProxyChatRoomPrivate;
|
friend class ProxyChatRoomPrivate;
|
||||||
|
|
@ -66,6 +67,7 @@ public:
|
||||||
virtual std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const = 0;
|
virtual std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const = 0;
|
||||||
virtual int getHistorySize () const = 0;
|
virtual int getHistorySize () const = 0;
|
||||||
|
|
||||||
|
virtual void deleteFromDb () = 0;
|
||||||
virtual void deleteHistory () = 0;
|
virtual void deleteHistory () = 0;
|
||||||
|
|
||||||
virtual std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const = 0;
|
virtual std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const = 0;
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,12 @@ int ChatRoom::getHistorySize () const {
|
||||||
return getCore()->getPrivate()->mainDb->getHistorySize(getChatRoomId());
|
return getCore()->getPrivate()->mainDb->getHistorySize(getChatRoomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatRoom::deleteFromDb () {
|
||||||
|
L_D();
|
||||||
|
Core::deleteChatRoom(this->getSharedFromThis());
|
||||||
|
d->setState(ChatRoom::State::Deleted);
|
||||||
|
}
|
||||||
|
|
||||||
void ChatRoom::deleteHistory () {
|
void ChatRoom::deleteHistory () {
|
||||||
getCore()->getPrivate()->mainDb->cleanHistory(getChatRoomId());
|
getCore()->getPrivate()->mainDb->cleanHistory(getChatRoomId());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ public:
|
||||||
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
|
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
|
||||||
int getHistorySize () const override;
|
int getHistorySize () const override;
|
||||||
|
|
||||||
|
void deleteFromDb () override;
|
||||||
void deleteHistory () override;
|
void deleteHistory () override;
|
||||||
|
|
||||||
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
|
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ public:
|
||||||
// ChatRoomListener
|
// ChatRoomListener
|
||||||
void onChatRoomInsertRequested (const std::shared_ptr<AbstractChatRoom> &chatRoom) override;
|
void onChatRoomInsertRequested (const std::shared_ptr<AbstractChatRoom> &chatRoom) override;
|
||||||
void onChatRoomInsertInDatabaseRequested (const std::shared_ptr<AbstractChatRoom> &chatRoom) override;
|
void onChatRoomInsertInDatabaseRequested (const std::shared_ptr<AbstractChatRoom> &chatRoom) override;
|
||||||
|
void onChatRoomDeleteRequested (const std::shared_ptr<AbstractChatRoom> &chatRoom) override;
|
||||||
|
|
||||||
// CallSessionListener
|
// CallSessionListener
|
||||||
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override;
|
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override;
|
||||||
|
|
@ -50,6 +51,8 @@ public:
|
||||||
private:
|
private:
|
||||||
CallSessionListener *callSessionListener = this;
|
CallSessionListener *callSessionListener = this;
|
||||||
ChatRoomListener *chatRoomListener = this;
|
ChatRoomListener *chatRoomListener = this;
|
||||||
|
ClientGroupChatRoom::CapabilitiesMask capabilities = ClientGroupChatRoom::Capabilities::Conference;
|
||||||
|
bool deletionOnTerminationEnabled = false;
|
||||||
|
|
||||||
L_DECLARE_PUBLIC(ClientGroupChatRoom);
|
L_DECLARE_PUBLIC(ClientGroupChatRoom);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ shared_ptr<CallSession> ClientGroupChatRoomPrivate::createSession () {
|
||||||
CallSessionParams csp;
|
CallSessionParams csp;
|
||||||
csp.addCustomHeader("Require", "recipient-list-invite");
|
csp.addCustomHeader("Require", "recipient-list-invite");
|
||||||
csp.addCustomContactParameter("text");
|
csp.addCustomContactParameter("text");
|
||||||
|
if (capabilities & ClientGroupChatRoom::Capabilities::OneToOne)
|
||||||
|
csp.addCustomHeader("One-To-One-Chat-Room", "true");
|
||||||
|
|
||||||
shared_ptr<Participant> focus = qConference->getPrivate()->focus;
|
shared_ptr<Participant> focus = qConference->getPrivate()->focus;
|
||||||
shared_ptr<CallSession> session = focus->getPrivate()->createSession(*q, &csp, false, callSessionListener);
|
shared_ptr<CallSession> session = focus->getPrivate()->createSession(*q, &csp, false, callSessionListener);
|
||||||
|
|
@ -111,6 +113,12 @@ void ClientGroupChatRoomPrivate::onChatRoomInsertInDatabaseRequested (const shar
|
||||||
q->getCore()->getPrivate()->insertChatRoomWithDb(chatRoom);
|
q->getCore()->getPrivate()->insertChatRoomWithDb(chatRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientGroupChatRoomPrivate::onChatRoomDeleteRequested (const shared_ptr<AbstractChatRoom> &chatRoom) {
|
||||||
|
L_Q();
|
||||||
|
q->getCore()->deleteChatRoom(q->getSharedFromThis());
|
||||||
|
setState(ClientGroupChatRoom::State::Deleted);
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ClientGroupChatRoomPrivate::onCallSessionSetReleased (const shared_ptr<const CallSession> &session) {
|
void ClientGroupChatRoomPrivate::onCallSessionSetReleased (const shared_ptr<const CallSession> &session) {
|
||||||
|
|
@ -164,6 +172,7 @@ ClientGroupChatRoom::ClientGroupChatRoom (
|
||||||
const shared_ptr<Core> &core,
|
const shared_ptr<Core> &core,
|
||||||
const ChatRoomId &chatRoomId,
|
const ChatRoomId &chatRoomId,
|
||||||
shared_ptr<Participant> &me,
|
shared_ptr<Participant> &me,
|
||||||
|
AbstractChatRoom::CapabilitiesMask capabilities,
|
||||||
const string &subject,
|
const string &subject,
|
||||||
list<shared_ptr<Participant>> &&participants,
|
list<shared_ptr<Participant>> &&participants,
|
||||||
unsigned int lastNotifyId
|
unsigned int lastNotifyId
|
||||||
|
|
@ -189,7 +198,8 @@ shared_ptr<Core> ClientGroupChatRoom::getCore () const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientGroupChatRoom::CapabilitiesMask ClientGroupChatRoom::getCapabilities () const {
|
ClientGroupChatRoom::CapabilitiesMask ClientGroupChatRoom::getCapabilities () const {
|
||||||
return Capabilities::Conference;
|
L_D();
|
||||||
|
return d->capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientGroupChatRoom::hasBeenLeft () const {
|
bool ClientGroupChatRoom::hasBeenLeft () const {
|
||||||
|
|
@ -208,6 +218,16 @@ const IdentityAddress &ClientGroupChatRoom::getConferenceAddress () const {
|
||||||
return RemoteConference::getConferenceAddress();
|
return RemoteConference::getConferenceAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientGroupChatRoom::deleteFromDb () {
|
||||||
|
L_D();
|
||||||
|
if (!hasBeenLeft()) {
|
||||||
|
d->deletionOnTerminationEnabled = true;
|
||||||
|
leave();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->chatRoomListener->onChatRoomDeleteRequested(getSharedFromThis());
|
||||||
|
}
|
||||||
|
|
||||||
void ClientGroupChatRoom::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) {
|
void ClientGroupChatRoom::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) {
|
||||||
list<IdentityAddress> addresses;
|
list<IdentityAddress> addresses;
|
||||||
addresses.push_back(addr);
|
addresses.push_back(addr);
|
||||||
|
|
@ -231,6 +251,19 @@ void ClientGroupChatRoom::addParticipants (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((getState() == ChatRoom::State::Created) && (d->capabilities & ClientGroupChatRoom::Capabilities::OneToOne)) {
|
||||||
|
lError() << "Cannot add more participants to a OneToOne ClientGroupChatRoom";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((getState() == ChatRoom::State::Instantiated)
|
||||||
|
&& (addressesList.size() == 1)
|
||||||
|
&& (linphone_config_get_bool(linphone_core_get_config(L_GET_C_BACK_PTR(getCore())),
|
||||||
|
"misc", "one_to_one_chat_room_enabled", TRUE))
|
||||||
|
) {
|
||||||
|
d->capabilities |= ClientGroupChatRoom::Capabilities::OneToOne;
|
||||||
|
}
|
||||||
|
|
||||||
Content content;
|
Content content;
|
||||||
content.setBody(getResourceLists(addressesList));
|
content.setBody(getResourceLists(addressesList));
|
||||||
content.setContentType("application/resource-lists+xml");
|
content.setContentType("application/resource-lists+xml");
|
||||||
|
|
@ -372,6 +405,11 @@ void ClientGroupChatRoom::onConferenceCreated (const IdentityAddress &addr) {
|
||||||
d->chatRoomListener->onChatRoomInsertRequested(getSharedFromThis());
|
d->chatRoomListener->onChatRoomInsertRequested(getSharedFromThis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientGroupChatRoom::onConferenceKeywordsChanged (const vector<string> &keywords) {
|
||||||
|
L_D();
|
||||||
|
d->capabilities |= ClientGroupChatRoom::Capabilities::OneToOne;
|
||||||
|
}
|
||||||
|
|
||||||
void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) {
|
void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) {
|
||||||
L_D();
|
L_D();
|
||||||
L_D_T(RemoteConference, dConference);
|
L_D_T(RemoteConference, dConference);
|
||||||
|
|
@ -382,6 +420,10 @@ void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) {
|
||||||
time(nullptr),
|
time(nullptr),
|
||||||
d->chatRoomId
|
d->chatRoomId
|
||||||
));
|
));
|
||||||
|
if (d->deletionOnTerminationEnabled) {
|
||||||
|
d->deletionOnTerminationEnabled = false;
|
||||||
|
d->chatRoomListener->onChatRoomDeleteRequested(getSharedFromThis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) {
|
void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class ClientGroupChatRoomPrivate;
|
||||||
class LINPHONE_PUBLIC ClientGroupChatRoom : public ChatRoom, public RemoteConference {
|
class LINPHONE_PUBLIC ClientGroupChatRoom : public ChatRoom, public RemoteConference {
|
||||||
friend class BasicToClientGroupChatRoomPrivate;
|
friend class BasicToClientGroupChatRoomPrivate;
|
||||||
friend class ClientGroupToBasicChatRoomPrivate;
|
friend class ClientGroupToBasicChatRoomPrivate;
|
||||||
|
friend class Core;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
L_OVERRIDE_SHARED_FROM_THIS(ClientGroupChatRoom);
|
L_OVERRIDE_SHARED_FROM_THIS(ClientGroupChatRoom);
|
||||||
|
|
@ -48,6 +49,7 @@ public:
|
||||||
const std::shared_ptr<Core> &core,
|
const std::shared_ptr<Core> &core,
|
||||||
const ChatRoomId &chatRoomId,
|
const ChatRoomId &chatRoomId,
|
||||||
std::shared_ptr<Participant> &me,
|
std::shared_ptr<Participant> &me,
|
||||||
|
AbstractChatRoom::CapabilitiesMask capabilities,
|
||||||
const std::string &subject,
|
const std::string &subject,
|
||||||
std::list<std::shared_ptr<Participant>> &&participants,
|
std::list<std::shared_ptr<Participant>> &&participants,
|
||||||
unsigned int lastNotifyId
|
unsigned int lastNotifyId
|
||||||
|
|
@ -63,6 +65,8 @@ public:
|
||||||
bool canHandleParticipants () const override;
|
bool canHandleParticipants () const override;
|
||||||
bool canHandleCpim () const override;
|
bool canHandleCpim () const override;
|
||||||
|
|
||||||
|
void deleteFromDb () override;
|
||||||
|
|
||||||
void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override;
|
void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override;
|
||||||
void addParticipants (const std::list<IdentityAddress> &addresses, const CallSessionParams *params, bool hasMedia) override;
|
void addParticipants (const std::list<IdentityAddress> &addresses, const CallSessionParams *params, bool hasMedia) override;
|
||||||
|
|
||||||
|
|
@ -88,6 +92,7 @@ private:
|
||||||
// ALL METHODS AFTER THIS POINT.
|
// ALL METHODS AFTER THIS POINT.
|
||||||
|
|
||||||
void onConferenceCreated (const IdentityAddress &addr) override;
|
void onConferenceCreated (const IdentityAddress &addr) override;
|
||||||
|
void onConferenceKeywordsChanged (const std::vector<std::string> &keywords) override;
|
||||||
void onConferenceTerminated (const IdentityAddress &addr) override;
|
void onConferenceTerminated (const IdentityAddress &addr) override;
|
||||||
void onFirstNotifyReceived (const IdentityAddress &addr) override;
|
void onFirstNotifyReceived (const IdentityAddress &addr) override;
|
||||||
void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) override;
|
void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) override;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,12 @@ public:
|
||||||
q->getCore()->getPrivate()->insertChatRoomWithDb(q->getSharedFromThis());
|
q->getCore()->getPrivate()->insertChatRoomWithDb(q->getSharedFromThis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onChatRoomDeleteRequested (const shared_ptr<AbstractChatRoom> &chatRoom) override {
|
||||||
|
L_Q();
|
||||||
|
q->getCore()->deleteChatRoom(q->getSharedFromThis());
|
||||||
|
setState(AbstractChatRoom::State::Deleted);
|
||||||
|
}
|
||||||
|
|
||||||
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override {
|
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override {
|
||||||
if (!(chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference))
|
if (!(chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference))
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,11 @@ int ProxyChatRoom::getHistorySize () const {
|
||||||
return d->chatRoom->getHistorySize();
|
return d->chatRoom->getHistorySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProxyChatRoom::deleteFromDb () {
|
||||||
|
L_D();
|
||||||
|
d->chatRoom->deleteFromDb();
|
||||||
|
}
|
||||||
|
|
||||||
void ProxyChatRoom::deleteHistory () {
|
void ProxyChatRoom::deleteHistory () {
|
||||||
L_D();
|
L_D();
|
||||||
d->chatRoom->deleteHistory();
|
d->chatRoom->deleteHistory();
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ public:
|
||||||
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
|
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
|
||||||
int getHistorySize () const override;
|
int getHistorySize () const override;
|
||||||
|
|
||||||
|
void deleteFromDb () override;
|
||||||
void deleteHistory () override;
|
void deleteHistory () override;
|
||||||
|
|
||||||
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
|
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ public:
|
||||||
|
|
||||||
void confirmCreation ();
|
void confirmCreation ();
|
||||||
void confirmJoining (SalCallOp *op);
|
void confirmJoining (SalCallOp *op);
|
||||||
|
void confirmRecreation (SalCallOp *op);
|
||||||
|
|
||||||
IdentityAddress generateConferenceAddress (const std::shared_ptr<Participant> &me) const;
|
IdentityAddress generateConferenceAddress (const std::shared_ptr<Participant> &me) const;
|
||||||
|
|
||||||
|
|
@ -43,10 +44,9 @@ public:
|
||||||
void update (SalCallOp *op);
|
void update (SalCallOp *op);
|
||||||
|
|
||||||
void dispatchMessage (const IdentityAddress &fromAddress, const Content &content);
|
void dispatchMessage (const IdentityAddress &fromAddress, const Content &content);
|
||||||
|
|
||||||
void setConferenceAddress (const IdentityAddress &conferenceAddress);
|
void setConferenceAddress (const IdentityAddress &conferenceAddress);
|
||||||
void setParticipantDevices (const IdentityAddress &addr, const std::list<IdentityAddress> &devices);
|
void setParticipantDevices (const IdentityAddress &addr, const std::list<IdentityAddress> &devices);
|
||||||
void addCompatibleParticipants (const IdentityAddress &deviceAddr, const std::list<IdentityAddress> &participantCompatible);
|
void addCompatibleParticipants (const IdentityAddress &deviceAddr, const std::list<IdentityAddress> &compatibleParticipants);
|
||||||
|
|
||||||
LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) override;
|
LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) override;
|
||||||
|
|
||||||
|
|
@ -63,12 +63,14 @@ private:
|
||||||
// CallSessionListener
|
// CallSessionListener
|
||||||
void onCallSessionStateChanged (
|
void onCallSessionStateChanged (
|
||||||
const std::shared_ptr<const CallSession> &session,
|
const std::shared_ptr<const CallSession> &session,
|
||||||
CallSession::State state,
|
CallSession::State newState,
|
||||||
const std::string &message
|
const std::string &message
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
std::list<std::shared_ptr<Participant>> removedParticipants;
|
std::list<std::shared_ptr<Participant>> removedParticipants;
|
||||||
ChatRoomListener *chatRoomListener = this;
|
ChatRoomListener *chatRoomListener = this;
|
||||||
|
ServerGroupChatRoom::CapabilitiesMask capabilities = ServerGroupChatRoom::Capabilities::Conference;
|
||||||
|
bool joiningPendingAfterCreation = false;
|
||||||
|
|
||||||
L_DECLARE_PUBLIC(ServerGroupChatRoom);
|
L_DECLARE_PUBLIC(ServerGroupChatRoom);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ void ServerGroupChatRoomPrivate::confirmCreation () {}
|
||||||
|
|
||||||
void ServerGroupChatRoomPrivate::confirmJoining (SalCallOp *) {}
|
void ServerGroupChatRoomPrivate::confirmJoining (SalCallOp *) {}
|
||||||
|
|
||||||
|
void ServerGroupChatRoomPrivate::confirmRecreation (SalCallOp *) {}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
IdentityAddress ServerGroupChatRoomPrivate::generateConferenceAddress (const shared_ptr<Participant> &me) const {
|
IdentityAddress ServerGroupChatRoomPrivate::generateConferenceAddress (const shared_ptr<Participant> &me) const {
|
||||||
|
|
@ -110,6 +112,7 @@ LocalConference(core, IdentityAddress(op->get_to()), nullptr) {
|
||||||
ServerGroupChatRoom::ServerGroupChatRoom (
|
ServerGroupChatRoom::ServerGroupChatRoom (
|
||||||
const shared_ptr<Core> &core,
|
const shared_ptr<Core> &core,
|
||||||
const IdentityAddress &peerAddress,
|
const IdentityAddress &peerAddress,
|
||||||
|
AbstractChatRoom::CapabilitiesMask capabilities,
|
||||||
const string &subject,
|
const string &subject,
|
||||||
list<shared_ptr<Participant>> &&participants,
|
list<shared_ptr<Participant>> &&participants,
|
||||||
unsigned int lastNotifyId
|
unsigned int lastNotifyId
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,16 @@ public:
|
||||||
ServerGroupChatRoom (
|
ServerGroupChatRoom (
|
||||||
const std::shared_ptr<Core> &core,
|
const std::shared_ptr<Core> &core,
|
||||||
const IdentityAddress &peerAddress,
|
const IdentityAddress &peerAddress,
|
||||||
|
AbstractChatRoom::CapabilitiesMask capabilities,
|
||||||
const std::string &subject,
|
const std::string &subject,
|
||||||
std::list<std::shared_ptr<Participant>> &&participants,
|
std::list<std::shared_ptr<Participant>> &&participants,
|
||||||
unsigned int lastNotifyId
|
unsigned int lastNotifyId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std::shared_ptr<Core> getCore () const;
|
||||||
|
|
||||||
|
std::shared_ptr<Participant> findParticipant (const std::shared_ptr<const CallSession> &session) const;
|
||||||
|
|
||||||
CapabilitiesMask getCapabilities () const override;
|
CapabilitiesMask getCapabilities () const override;
|
||||||
bool hasBeenLeft () const override;
|
bool hasBeenLeft () const override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "linphone/utils/general.h"
|
#include "linphone/utils/general.h"
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ class IdentityAddress;
|
||||||
class ConferenceListener {
|
class ConferenceListener {
|
||||||
public:
|
public:
|
||||||
virtual void onConferenceCreated (const IdentityAddress &addr) = 0;
|
virtual void onConferenceCreated (const IdentityAddress &addr) = 0;
|
||||||
|
virtual void onConferenceKeywordsChanged (const std::vector<std::string> &keywords) {}
|
||||||
virtual void onConferenceTerminated (const IdentityAddress &addr) = 0;
|
virtual void onConferenceTerminated (const IdentityAddress &addr) = 0;
|
||||||
virtual void onFirstNotifyReceived (const IdentityAddress &addr) = 0;
|
virtual void onFirstNotifyReceived (const IdentityAddress &addr) = 0;
|
||||||
virtual void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) = 0;
|
virtual void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) = 0;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public:
|
||||||
void notifyFullState (const std::string ¬ify, const std::shared_ptr<ParticipantDevice> &device);
|
void notifyFullState (const std::string ¬ify, const std::shared_ptr<ParticipantDevice> &device);
|
||||||
void notifyAllExcept (const std::string ¬ify, const std::shared_ptr<Participant> &exceptParticipant);
|
void notifyAllExcept (const std::string ¬ify, const std::shared_ptr<Participant> &exceptParticipant);
|
||||||
void notifyAll (const std::string ¬ify);
|
void notifyAll (const std::string ¬ify);
|
||||||
std::string createNotifyFullState (int notifyId = -1);
|
std::string createNotifyFullState (int notifyId = -1, bool oneToOne = false);
|
||||||
std::string createNotifyMultipart (int notifyId);
|
std::string createNotifyMultipart (int notifyId);
|
||||||
std::string createNotifyParticipantAdded (const Address &addr, int notifyId = -1);
|
std::string createNotifyParticipantAdded (const Address &addr, int notifyId = -1);
|
||||||
std::string createNotifyParticipantRemoved (const Address &addr, int notifyId = -1);
|
std::string createNotifyParticipantRemoved (const Address &addr, int notifyId = -1);
|
||||||
|
|
|
||||||
|
|
@ -107,13 +107,17 @@ string LocalConferenceEventHandlerPrivate::createNotify (ConferenceType confInfo
|
||||||
return notify.str();
|
return notify.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
string LocalConferenceEventHandlerPrivate::createNotifyFullState (int notifyId) {
|
string LocalConferenceEventHandlerPrivate::createNotifyFullState (int notifyId, bool oneToOne) {
|
||||||
string entity = conf->getConferenceAddress().asString();
|
string entity = conf->getConferenceAddress().asString();
|
||||||
string subject = conf->getSubject();
|
string subject = conf->getSubject();
|
||||||
ConferenceType confInfo = ConferenceType(entity);
|
ConferenceType confInfo = ConferenceType(entity);
|
||||||
UsersType users;
|
UsersType users;
|
||||||
ConferenceDescriptionType confDescr = ConferenceDescriptionType();
|
ConferenceDescriptionType confDescr = ConferenceDescriptionType();
|
||||||
confDescr.setSubject(subject);
|
confDescr.setSubject(subject);
|
||||||
|
if (oneToOne) {
|
||||||
|
KeywordsType keywords(sizeof(char), "one-to-one");
|
||||||
|
confDescr.setKeywords(keywords);
|
||||||
|
}
|
||||||
confInfo.setUsers(users);
|
confInfo.setUsers(users);
|
||||||
confInfo.setConferenceDescription((const ConferenceDescriptionType) confDescr);
|
confInfo.setConferenceDescription((const ConferenceDescriptionType) confDescr);
|
||||||
|
|
||||||
|
|
@ -357,18 +361,13 @@ string LocalConferenceEventHandlerPrivate::createNotifyParticipantDeviceRemoved
|
||||||
LocalConferenceEventHandler::LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify) :
|
LocalConferenceEventHandler::LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify) :
|
||||||
Object(*new LocalConferenceEventHandlerPrivate) {
|
Object(*new LocalConferenceEventHandlerPrivate) {
|
||||||
L_D();
|
L_D();
|
||||||
xercesc::XMLPlatformUtils::Initialize();
|
|
||||||
d->conf = localConference;
|
d->conf = localConference;
|
||||||
d->lastNotify = notify;
|
d->lastNotify = notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalConferenceEventHandler::~LocalConferenceEventHandler () {
|
|
||||||
xercesc::XMLPlatformUtils::Terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev) {
|
void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev, bool oneToOne) {
|
||||||
L_D();
|
L_D();
|
||||||
const LinphoneAddress *lAddr = linphone_event_get_from(lev);
|
const LinphoneAddress *lAddr = linphone_event_get_from(lev);
|
||||||
char *addrStr = linphone_address_as_string(lAddr);
|
char *addrStr = linphone_address_as_string(lAddr);
|
||||||
|
|
@ -396,7 +395,7 @@ void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev) {
|
||||||
device->setConferenceSubscribeEvent(lev);
|
device->setConferenceSubscribeEvent(lev);
|
||||||
if (lastNotify == 0) {
|
if (lastNotify == 0) {
|
||||||
lInfo() << "Sending initial notify of conference:" << d->conf->getConferenceAddress().asString() << " to: " << device->getAddress().asString();
|
lInfo() << "Sending initial notify of conference:" << d->conf->getConferenceAddress().asString() << " to: " << device->getAddress().asString();
|
||||||
d->notifyFullState(d->createNotifyFullState(static_cast<int>(d->lastNotify)), device);
|
d->notifyFullState(d->createNotifyFullState(static_cast<int>(d->lastNotify), oneToOne), device);
|
||||||
} else if (lastNotify < d->lastNotify) {
|
} else if (lastNotify < d->lastNotify) {
|
||||||
lInfo() << "Sending all missed notify [" << lastNotify << "-" << d->lastNotify <<
|
lInfo() << "Sending all missed notify [" << lastNotify << "-" << d->lastNotify <<
|
||||||
"] for conference:" << d->conf->getConferenceAddress().asString() <<
|
"] for conference:" << d->conf->getConferenceAddress().asString() <<
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,8 @@ class LocalConferenceEventHandlerPrivate;
|
||||||
class LocalConferenceEventHandler : public Object {
|
class LocalConferenceEventHandler : public Object {
|
||||||
public:
|
public:
|
||||||
LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify = 0);
|
LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify = 0);
|
||||||
~LocalConferenceEventHandler ();
|
|
||||||
|
|
||||||
void subscribeReceived (LinphoneEvent *lev);
|
void subscribeReceived (LinphoneEvent *lev, bool oneToOne = false);
|
||||||
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantAdded (const Address &addr);
|
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantAdded (const Address &addr);
|
||||||
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantRemoved (const Address &addr);
|
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantRemoved (const Address &addr);
|
||||||
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantSetAdmin (const Address &addr, bool isAdmin);
|
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantSetAdmin (const Address &addr, bool isAdmin);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "linphone/utils/utils.h"
|
#include "linphone/utils/utils.h"
|
||||||
|
|
||||||
#include "conference/remote-conference.h"
|
#include "conference/remote-conference.h"
|
||||||
|
|
@ -53,11 +55,10 @@ void RemoteConferenceEventHandlerPrivate::simpleNotifyReceived (const string &xm
|
||||||
|
|
||||||
IdentityAddress entityAddress(confInfo->getEntity().c_str());
|
IdentityAddress entityAddress(confInfo->getEntity().c_str());
|
||||||
if (entityAddress == chatRoomId.getPeerAddress()) {
|
if (entityAddress == chatRoomId.getPeerAddress()) {
|
||||||
if (
|
if (confInfo->getConferenceDescription().present()) {
|
||||||
confInfo->getConferenceDescription().present() &&
|
if (confInfo->getConferenceDescription().get().getSubject().present() &&
|
||||||
confInfo->getConferenceDescription().get().getSubject().present() &&
|
|
||||||
!confInfo->getConferenceDescription().get().getSubject().get().empty()
|
!confInfo->getConferenceDescription().get().getSubject().get().empty()
|
||||||
)
|
) {
|
||||||
confListener->onSubjectChanged(
|
confListener->onSubjectChanged(
|
||||||
make_shared<ConferenceSubjectEvent>(
|
make_shared<ConferenceSubjectEvent>(
|
||||||
tm,
|
tm,
|
||||||
|
|
@ -67,6 +68,17 @@ void RemoteConferenceEventHandlerPrivate::simpleNotifyReceived (const string &xm
|
||||||
),
|
),
|
||||||
isFullState
|
isFullState
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
if (confInfo->getConferenceDescription().get().getKeywords().present()
|
||||||
|
&& !confInfo->getConferenceDescription().get().getKeywords().get().empty()
|
||||||
|
) {
|
||||||
|
KeywordsType xmlKeywords = confInfo->getConferenceDescription().get().getKeywords().get();
|
||||||
|
vector<string> keywords;
|
||||||
|
for (const auto &k : xmlKeywords)
|
||||||
|
keywords.push_back(k);
|
||||||
|
confListener->onConferenceKeywordsChanged(keywords);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (confInfo->getVersion().present())
|
if (confInfo->getVersion().present())
|
||||||
lastNotify = confInfo->getVersion().get();
|
lastNotify = confInfo->getVersion().get();
|
||||||
|
|
||||||
|
|
@ -215,7 +227,6 @@ void RemoteConferenceEventHandlerPrivate::onRegistrationStateChanged (LinphonePr
|
||||||
RemoteConferenceEventHandler::RemoteConferenceEventHandler (RemoteConference *remoteConference) :
|
RemoteConferenceEventHandler::RemoteConferenceEventHandler (RemoteConference *remoteConference) :
|
||||||
Object(*new RemoteConferenceEventHandlerPrivate) {
|
Object(*new RemoteConferenceEventHandlerPrivate) {
|
||||||
L_D();
|
L_D();
|
||||||
xercesc::XMLPlatformUtils::Initialize();
|
|
||||||
d->conf = remoteConference;
|
d->conf = remoteConference;
|
||||||
d->conf->getCore()->getPrivate()->registerListener(d);
|
d->conf->getCore()->getPrivate()->registerListener(d);
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +234,6 @@ Object(*new RemoteConferenceEventHandlerPrivate) {
|
||||||
RemoteConferenceEventHandler::~RemoteConferenceEventHandler () {
|
RemoteConferenceEventHandler::~RemoteConferenceEventHandler () {
|
||||||
L_D();
|
L_D();
|
||||||
d->conf->getCore()->getPrivate()->unregisterListener(d);
|
d->conf->getCore()->getPrivate()->unregisterListener(d);
|
||||||
xercesc::XMLPlatformUtils::Terminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "content/content.h"
|
||||||
|
#include "content/content-type.h"
|
||||||
#include "handlers/local-conference-event-handler.h"
|
#include "handlers/local-conference-event-handler.h"
|
||||||
#include "local-conference-p.h"
|
#include "local-conference-p.h"
|
||||||
#include "participant-p.h"
|
#include "participant-p.h"
|
||||||
|
|
@ -63,20 +65,25 @@ void LocalConference::removeParticipant (const shared_ptr<const Participant> &pa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list<IdentityAddress> LocalConference::parseResourceLists (const string &xmlBody) {
|
list<IdentityAddress> LocalConference::parseResourceLists (const Content &content) {
|
||||||
istringstream data(xmlBody);
|
if ((content.getContentType() == ContentType::ResourceLists)
|
||||||
unique_ptr<Xsd::ResourceLists::ResourceLists> rl = LinphonePrivate::Xsd::ResourceLists::parseResourceLists(
|
&& (content.getContentDisposition() == "recipient-list")
|
||||||
|
) {
|
||||||
|
istringstream data(content.getBodyAsString());
|
||||||
|
unique_ptr<Xsd::ResourceLists::ResourceLists> rl(Xsd::ResourceLists::parseResourceLists(
|
||||||
data,
|
data,
|
||||||
Xsd::XmlSchema::Flags::dont_validate
|
Xsd::XmlSchema::Flags::dont_validate
|
||||||
);
|
));
|
||||||
list<IdentityAddress> addresses = list<IdentityAddress>();
|
list<IdentityAddress> addresses;
|
||||||
for (const auto &l : rl->getList()) {
|
for (const auto &l : rl->getList()) {
|
||||||
for (const auto &entry : l.getEntry()) {
|
for (const auto &entry : l.getEntry()) {
|
||||||
IdentityAddress addr(entry.getUri());
|
IdentityAddress addr(entry.getUri());
|
||||||
addresses.push_back(addr);
|
addresses.push_back(move(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return addresses;
|
return addresses;
|
||||||
|
}
|
||||||
|
return list<IdentityAddress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
LINPHONE_END_NAMESPACE
|
LINPHONE_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
LINPHONE_BEGIN_NAMESPACE
|
LINPHONE_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class Content;
|
||||||
class LocalConferencePrivate;
|
class LocalConferencePrivate;
|
||||||
|
|
||||||
class LocalConference : public Conference {
|
class LocalConference : public Conference {
|
||||||
|
|
@ -39,7 +40,7 @@ public:
|
||||||
void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override;
|
void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override;
|
||||||
void removeParticipant (const std::shared_ptr<const Participant> &participant) override;
|
void removeParticipant (const std::shared_ptr<const Participant> &participant) override;
|
||||||
|
|
||||||
std::list<IdentityAddress> parseResourceLists (const std::string &xmlBody);
|
static std::list<IdentityAddress> parseResourceLists (const Content &content);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
L_DECLARE_PRIVATE(LocalConference);
|
L_DECLARE_PRIVATE(LocalConference);
|
||||||
|
|
|
||||||
|
|
@ -252,21 +252,12 @@ void Core::deleteChatRoom (const shared_ptr<const AbstractChatRoom> &chatRoom) {
|
||||||
CorePrivate *d = chatRoom->getCore()->getPrivate();
|
CorePrivate *d = chatRoom->getCore()->getPrivate();
|
||||||
|
|
||||||
const ChatRoomId &chatRoomId = chatRoom->getChatRoomId();
|
const ChatRoomId &chatRoomId = chatRoom->getChatRoomId();
|
||||||
auto it = d->chatRoomsById.find(chatRoomId);
|
auto chatRoomsByIdIt = d->chatRoomsById.find(chatRoomId);
|
||||||
if (it != d->chatRoomsById.end()) {
|
if (chatRoomsByIdIt != d->chatRoomsById.end()) {
|
||||||
|
auto chatRoomsIt = find(d->chatRooms.begin(), d->chatRooms.end(), chatRoom);
|
||||||
// TODO: Remove me later.
|
L_ASSERT(chatRoomsIt != d->chatRooms.end());
|
||||||
auto it = find_if(
|
d->chatRooms.erase(chatRoomsIt);
|
||||||
d->chatRooms.begin(), d->chatRooms.end(),
|
d->chatRoomsById.erase(chatRoomsByIdIt);
|
||||||
[&chatRoomId](const shared_ptr<AbstractChatRoom> &chatRoom) {
|
|
||||||
return chatRoom->getChatRoomId() == chatRoomId;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// FIXME: Use this code in the future. (Wait for signals.)
|
|
||||||
// auto it = find(d->chatRooms.begin(), d->chatRooms.end(), chatRoom);
|
|
||||||
// L_ASSERT(it != d->chatRooms.end());
|
|
||||||
d->chatRooms.erase(it);
|
|
||||||
d->mainDb->deleteChatRoom(chatRoomId);
|
d->mainDb->deleteChatRoom(chatRoomId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <mediastreamer2/mscommon.h>
|
#include <mediastreamer2/mscommon.h>
|
||||||
|
#include <xercesc/util/PlatformUtils.hpp>
|
||||||
|
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
#include "core/core-listener.h"
|
#include "core/core-listener.h"
|
||||||
|
|
@ -52,7 +53,7 @@ void CorePrivate::init () {
|
||||||
uri = q->getDataPath() + LINPHONE_DB;
|
uri = q->getDataPath() + LINPHONE_DB;
|
||||||
}
|
}
|
||||||
|
|
||||||
lInfo() << "Opening " LINPHONE_DB "...";
|
lInfo() << "Opening linphone database: " << uri;
|
||||||
if (!mainDb->connect(backend, uri))
|
if (!mainDb->connect(backend, uri))
|
||||||
lFatal() << "Unable to open linphone database.";
|
lFatal() << "Unable to open linphone database.";
|
||||||
|
|
||||||
|
|
@ -91,10 +92,13 @@ void CorePrivate::notifyRegistrationStateChanged (LinphoneProxyConfig *cfg, Linp
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
Core::Core () : Object(*new CorePrivate) {}
|
Core::Core () : Object(*new CorePrivate) {
|
||||||
|
xercesc::XMLPlatformUtils::Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
Core::~Core () {
|
Core::~Core () {
|
||||||
lInfo() << "Destroying core: " << this;
|
lInfo() << "Destroying core: " << this;
|
||||||
|
xercesc::XMLPlatformUtils::Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Core> Core::create (LinphoneCore *cCore) {
|
shared_ptr<Core> Core::create (LinphoneCore *cCore) {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ private:
|
||||||
long long selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const;
|
long long selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const;
|
||||||
long long selectChatRoomId (const ChatRoomId &chatRoomId) const;
|
long long selectChatRoomId (const ChatRoomId &chatRoomId) const;
|
||||||
long long selectChatRoomParticipantId (long long chatRoomId, long long participantSipAddressId) const;
|
long long selectChatRoomParticipantId (long long chatRoomId, long long participantSipAddressId) const;
|
||||||
|
long long selectOneToOneChatRoomId (long long sipAddressIdA, long long sipAddressIdB) const;
|
||||||
|
|
||||||
void deleteContents (long long messageEventId);
|
void deleteContents (long long messageEventId);
|
||||||
void deleteChatRoomParticipant (long long chatRoomId, long long participantSipAddressId);
|
void deleteChatRoomParticipant (long long chatRoomId, long long participantSipAddressId);
|
||||||
|
|
|
||||||
|
|
@ -266,10 +266,7 @@ long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &cha
|
||||||
|
|
||||||
const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
|
const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
|
||||||
// Remove capabilities like `Proxy`.
|
// Remove capabilities like `Proxy`.
|
||||||
const int &capabilities = chatRoom->getCapabilities() & ChatRoom::CapabilitiesMask({
|
const int &capabilities = chatRoom->getCapabilities() & ~ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Proxy);
|
||||||
ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::RealTimeText,
|
|
||||||
ChatRoom::Capabilities::Conference, ChatRoom::Capabilities::Migratable
|
|
||||||
});
|
|
||||||
|
|
||||||
const string &subject = chatRoom->getSubject();
|
const string &subject = chatRoom->getSubject();
|
||||||
const int &flags = chatRoom->hasBeenLeft();
|
const int &flags = chatRoom->hasBeenLeft();
|
||||||
|
|
@ -409,6 +406,18 @@ long long MainDbPrivate::selectChatRoomParticipantId (long long chatRoomId, long
|
||||||
return session->got_data() ? id : -1;
|
return session->got_data() ? id : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long long MainDbPrivate::selectOneToOneChatRoomId (long long sipAddressIdA, long long sipAddressIdB) const {
|
||||||
|
long long id;
|
||||||
|
soci::session *session = dbSession.getBackendSession<soci::session>();
|
||||||
|
*session << "SELECT chat_room_id"
|
||||||
|
" FROM one_to_one_chat_room"
|
||||||
|
" WHERE participant_a_sip_address_id IN (:sipAddressIdA, :sipAddressIdB)"
|
||||||
|
" AND participant_b_sip_address_id IN (:sipAddressIdABis, :sipAddressIdBBis)",
|
||||||
|
soci::into(id),
|
||||||
|
soci::use(sipAddressIdA), soci::use(sipAddressIdB), soci::use(sipAddressIdA), soci::use(sipAddressIdB);
|
||||||
|
return session->got_data() ? id : -1;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void MainDbPrivate::deleteContents (long long messageEventId) {
|
void MainDbPrivate::deleteContents (long long messageEventId) {
|
||||||
|
|
@ -1372,6 +1381,26 @@ void MainDb::init () {
|
||||||
" ON DELETE CASCADE"
|
" ON DELETE CASCADE"
|
||||||
") " + charset;
|
") " + charset;
|
||||||
|
|
||||||
|
if (linphone_core_conference_server_enabled(getCore()->getCCore())) {
|
||||||
|
*session <<
|
||||||
|
"CREATE TABLE IF NOT EXISTS one_to_one_chat_room ("
|
||||||
|
" chat_room_id" + primaryKeyStr("BIGINT UNSIGNED") + ","
|
||||||
|
|
||||||
|
" participant_a_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL,"
|
||||||
|
" participant_b_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL,"
|
||||||
|
|
||||||
|
" FOREIGN KEY (chat_room_id)"
|
||||||
|
" REFERENCES chat_room(id)"
|
||||||
|
" ON DELETE CASCADE,"
|
||||||
|
" FOREIGN KEY (participant_a_sip_address_id)"
|
||||||
|
" REFERENCES sip_address(id)"
|
||||||
|
" ON DELETE CASCADE,"
|
||||||
|
" FOREIGN KEY (participant_b_sip_address_id)"
|
||||||
|
" REFERENCES sip_address(id)"
|
||||||
|
" ON DELETE CASCADE"
|
||||||
|
") " + charset;
|
||||||
|
}
|
||||||
|
|
||||||
*session <<
|
*session <<
|
||||||
"CREATE TABLE IF NOT EXISTS chat_room_participant ("
|
"CREATE TABLE IF NOT EXISTS chat_room_participant ("
|
||||||
" id" + primaryKeyStr("BIGINT UNSIGNED") + ","
|
" id" + primaryKeyStr("BIGINT UNSIGNED") + ","
|
||||||
|
|
@ -2433,6 +2462,7 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms () const {
|
||||||
core,
|
core,
|
||||||
chatRoomId,
|
chatRoomId,
|
||||||
me,
|
me,
|
||||||
|
capabilities,
|
||||||
subject,
|
subject,
|
||||||
move(participants),
|
move(participants),
|
||||||
lastNotifyId
|
lastNotifyId
|
||||||
|
|
@ -2447,6 +2477,7 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms () const {
|
||||||
chatRoom = make_shared<ServerGroupChatRoom>(
|
chatRoom = make_shared<ServerGroupChatRoom>(
|
||||||
core,
|
core,
|
||||||
chatRoomId.getPeerAddress(),
|
chatRoomId.getPeerAddress(),
|
||||||
|
capabilities,
|
||||||
subject,
|
subject,
|
||||||
move(participants),
|
move(participants),
|
||||||
lastNotifyId
|
lastNotifyId
|
||||||
|
|
@ -2600,17 +2631,6 @@ IdentityAddress MainDb::findOneToOneConferenceChatRoomAddress (
|
||||||
const IdentityAddress &participantA,
|
const IdentityAddress &participantA,
|
||||||
const IdentityAddress &participantB
|
const IdentityAddress &participantB
|
||||||
) const {
|
) const {
|
||||||
static const string query = "SELECT sip_address.value"
|
|
||||||
" FROM chat_room, sip_address"
|
|
||||||
" WHERE capabilities = " + Utils::toString(static_cast<int>(ChatRoom::Capabilities::Conference)) +
|
|
||||||
" AND (SELECT COUNT(*) FROM chat_room_participant WHERE chat_room_id = chat_room.id) = 2"
|
|
||||||
" AND (SELECT COUNT(*) FROM chat_room_participant WHERE chat_room_id = chat_room.id AND participant_sip_address_id IN ("
|
|
||||||
" (SELECT id FROM sip_address WHERE value = :participantSipAddressA),"
|
|
||||||
" (SELECT id FROM sip_address WHERE value = :participantSipAddressB)"
|
|
||||||
" )) = 2"
|
|
||||||
" AND sip_address.id = peer_sip_address_id"
|
|
||||||
" LIMIT 1";
|
|
||||||
|
|
||||||
L_D();
|
L_D();
|
||||||
|
|
||||||
if (!isConnected()) {
|
if (!isConnected()) {
|
||||||
|
|
@ -2618,24 +2638,63 @@ IdentityAddress MainDb::findOneToOneConferenceChatRoomAddress (
|
||||||
return IdentityAddress();
|
return IdentityAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string chatRoomAddress;
|
||||||
|
|
||||||
L_BEGIN_LOG_EXCEPTION
|
L_BEGIN_LOG_EXCEPTION
|
||||||
|
|
||||||
soci::session *session = d->dbSession.getBackendSession<soci::session>();
|
soci::session *session = d->dbSession.getBackendSession<soci::session>();
|
||||||
soci::transaction tr(*session);
|
soci::transaction tr(*session);
|
||||||
|
|
||||||
const string &participantSipAddressA = participantA.asString();
|
const long long &participantASipAddressId = d->selectSipAddressId(participantA.asString());
|
||||||
const string &participantSipAddressB = participantB.asString();
|
const long long &participantBSipAddressId = d->selectSipAddressId(participantB.asString());
|
||||||
|
if ((participantASipAddressId == -1) || (participantBSipAddressId == -1))
|
||||||
|
return IdentityAddress();
|
||||||
|
|
||||||
string chatRoomAddress;
|
const long long &chatRoomId = d->selectOneToOneChatRoomId(participantASipAddressId, participantBSipAddressId);
|
||||||
|
|
||||||
*session << query, soci::use(participantSipAddressA), soci::use(participantSipAddressB), soci::into(chatRoomAddress);
|
*session << "SELECT sip_address.value"
|
||||||
|
" FROM chat_room, sip_address"
|
||||||
return IdentityAddress(chatRoomAddress);
|
" WHERE chat_room.id = :chatRoomId AND peer_sip_address_id = sip_address.id",
|
||||||
|
soci::use(chatRoomId), soci::into(chatRoomAddress);
|
||||||
|
|
||||||
L_END_LOG_EXCEPTION
|
L_END_LOG_EXCEPTION
|
||||||
|
|
||||||
// Soci error.
|
return IdentityAddress(chatRoomAddress);
|
||||||
return IdentityAddress();
|
}
|
||||||
|
|
||||||
|
void MainDb::insertOneToOneConferenceChatRoom (const shared_ptr<AbstractChatRoom> &chatRoom) {
|
||||||
|
L_D();
|
||||||
|
L_ASSERT(linphone_core_conference_server_enabled(chatRoom->getCore()->getCCore()));
|
||||||
|
L_ASSERT(chatRoom->getCapabilities() & ChatRoom::Capabilities::OneToOne);
|
||||||
|
|
||||||
|
if (!isConnected()) {
|
||||||
|
lWarning() << "Unable to insert one to one conference chat room. Not connected.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
L_BEGIN_LOG_EXCEPTION
|
||||||
|
|
||||||
|
soci::session *session = d->dbSession.getBackendSession<soci::session>();
|
||||||
|
soci::transaction tr(*session);
|
||||||
|
|
||||||
|
const list<shared_ptr<Participant>> &participants = chatRoom->getParticipants();
|
||||||
|
const long long &participantASipAddressId = d->selectSipAddressId(participants.front()->getAddress().asString());
|
||||||
|
const long long &participantBSipAddressId = d->selectSipAddressId(participants.back()->getAddress().asString());
|
||||||
|
L_ASSERT(participantASipAddressId != -1);
|
||||||
|
L_ASSERT(participantBSipAddressId != -1);
|
||||||
|
|
||||||
|
long long chatRoomId = d->selectOneToOneChatRoomId(participantASipAddressId, participantBSipAddressId);
|
||||||
|
if (chatRoomId == -1) {
|
||||||
|
chatRoomId = d->selectChatRoomId(chatRoom->getChatRoomId());
|
||||||
|
*session << "INSERT INTO one_to_one_chat_room ("
|
||||||
|
" chat_room_id, participant_a_sip_address_id, participant_b_sip_address_id"
|
||||||
|
") VALUES (:chatRoomId, :participantASipAddressId, :participantBSipAddressId)",
|
||||||
|
soci::use(chatRoomId), soci::use(participantASipAddressId), soci::use(participantBSipAddressId);
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.commit();
|
||||||
|
|
||||||
|
L_END_LOG_EXCEPTION
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainDb::enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable) {
|
void MainDb::enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable) {
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,8 @@ public:
|
||||||
const IdentityAddress &participantB
|
const IdentityAddress &participantB
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
void insertOneToOneConferenceChatRoom (const std::shared_ptr<AbstractChatRoom> &chatRoom);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Other.
|
// Other.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -449,6 +449,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onConferenceCreated (const IdentityAddress &addr) override;
|
void onConferenceCreated (const IdentityAddress &addr) override;
|
||||||
|
void onConferenceKeywordsChanged (const vector<string> &keywords) override;
|
||||||
void onConferenceTerminated (const IdentityAddress &addr) override;
|
void onConferenceTerminated (const IdentityAddress &addr) override;
|
||||||
void onFirstNotifyReceived (const IdentityAddress &addr) override;
|
void onFirstNotifyReceived (const IdentityAddress &addr) override;
|
||||||
void onParticipantAdded (const shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) override;
|
void onParticipantAdded (const shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) override;
|
||||||
|
|
@ -463,6 +464,7 @@ public:
|
||||||
map<string, bool> participants;
|
map<string, bool> participants;
|
||||||
map<string, int> participantDevices;
|
map<string, int> participantDevices;
|
||||||
string confSubject;
|
string confSubject;
|
||||||
|
bool oneToOne = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConferenceEventTester::ConferenceEventTester (const shared_ptr<Core> &core, const Address &confAddr)
|
ConferenceEventTester::ConferenceEventTester (const shared_ptr<Core> &core, const Address &confAddr)
|
||||||
|
|
@ -476,6 +478,13 @@ ConferenceEventTester::~ConferenceEventTester () {
|
||||||
|
|
||||||
void ConferenceEventTester::onConferenceCreated (const IdentityAddress &addr) {}
|
void ConferenceEventTester::onConferenceCreated (const IdentityAddress &addr) {}
|
||||||
|
|
||||||
|
void ConferenceEventTester::onConferenceKeywordsChanged (const vector<string> &keywords) {
|
||||||
|
for (const auto &k : keywords) {
|
||||||
|
if (k == "one-to-one")
|
||||||
|
oneToOne = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConferenceEventTester::onConferenceTerminated (const IdentityAddress &addr) {}
|
void ConferenceEventTester::onConferenceTerminated (const IdentityAddress &addr) {}
|
||||||
|
|
||||||
void ConferenceEventTester::onFirstNotifyReceived (const IdentityAddress &addr) {}
|
void ConferenceEventTester::onFirstNotifyReceived (const IdentityAddress &addr) {}
|
||||||
|
|
@ -1277,6 +1286,42 @@ void send_device_removed_notify() {
|
||||||
linphone_core_manager_destroy(pauline);
|
linphone_core_manager_destroy(pauline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void one_to_one_keyword () {
|
||||||
|
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
|
||||||
|
LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
|
||||||
|
char *identityStr = linphone_address_as_string(pauline->identity);
|
||||||
|
Address addr(identityStr);
|
||||||
|
bctbx_free(identityStr);
|
||||||
|
shared_ptr<ConferenceEventTester> tester = make_shared<ConferenceEventTester>(marie->lc->cppPtr, addr);
|
||||||
|
shared_ptr<LocalConference> localConf = make_shared<LocalConference>(pauline->lc->cppPtr, addr, nullptr);
|
||||||
|
LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri);
|
||||||
|
char *bobAddrStr = linphone_address_as_string(cBobAddr);
|
||||||
|
Address bobAddr(bobAddrStr);
|
||||||
|
bctbx_free(bobAddrStr);
|
||||||
|
linphone_address_unref(cBobAddr);
|
||||||
|
|
||||||
|
CallSessionParams params;
|
||||||
|
localConf->addParticipant(bobAddr, ¶ms, false);
|
||||||
|
LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(
|
||||||
|
L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler)
|
||||||
|
);
|
||||||
|
const_cast<IdentityAddress &>(localConf->getConferenceAddress()) = addr;
|
||||||
|
string notify = localHandlerPrivate->createNotifyFullState(-1, true);
|
||||||
|
|
||||||
|
const_cast<IdentityAddress &>(tester->handler->getChatRoomId().getPeerAddress()) = addr;
|
||||||
|
tester->handler->notifyReceived(notify);
|
||||||
|
|
||||||
|
BC_ASSERT_EQUAL(tester->participantDevices.size(), 1, int, "%d");
|
||||||
|
BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end());
|
||||||
|
BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d");
|
||||||
|
BC_ASSERT_TRUE(tester->oneToOne);
|
||||||
|
|
||||||
|
tester = nullptr;
|
||||||
|
localConf = nullptr;
|
||||||
|
linphone_core_manager_destroy(marie);
|
||||||
|
linphone_core_manager_destroy(pauline);
|
||||||
|
}
|
||||||
|
|
||||||
test_t conference_event_tests[] = {
|
test_t conference_event_tests[] = {
|
||||||
TEST_NO_TAG("First notify parsing", first_notify_parsing),
|
TEST_NO_TAG("First notify parsing", first_notify_parsing),
|
||||||
TEST_NO_TAG("First notify parsing wrong conf", first_notify_parsing_wrong_conf),
|
TEST_NO_TAG("First notify parsing wrong conf", first_notify_parsing_wrong_conf),
|
||||||
|
|
@ -1292,7 +1337,8 @@ test_t conference_event_tests[] = {
|
||||||
TEST_NO_TAG("Send participant unadmined notify", send_unadmined_notify),
|
TEST_NO_TAG("Send participant unadmined notify", send_unadmined_notify),
|
||||||
TEST_NO_TAG("Send subject changed notify", send_subject_changed_notify),
|
TEST_NO_TAG("Send subject changed notify", send_subject_changed_notify),
|
||||||
TEST_NO_TAG("Send device added notify", send_device_added_notify),
|
TEST_NO_TAG("Send device added notify", send_device_added_notify),
|
||||||
TEST_NO_TAG("Send device removed notify", send_device_removed_notify)
|
TEST_NO_TAG("Send device removed notify", send_device_removed_notify),
|
||||||
|
TEST_NO_TAG("one-to-one keyword", one_to_one_keyword)
|
||||||
};
|
};
|
||||||
|
|
||||||
test_suite_t conference_event_test_suite = {
|
test_suite_t conference_event_test_suite = {
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ static void chat_room_state_changed (LinphoneChatRoom *cr, LinphoneChatRoomState
|
||||||
case LinphoneChatRoomStateCreationFailed:
|
case LinphoneChatRoomStateCreationFailed:
|
||||||
manager->stat.number_of_LinphoneChatRoomStateCreationFailed++;
|
manager->stat.number_of_LinphoneChatRoomStateCreationFailed++;
|
||||||
break;
|
break;
|
||||||
|
case LinphoneChatRoomStateDeleted:
|
||||||
|
manager->stat.number_of_LinphoneChatRoomStateDeleted++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2033,10 +2036,72 @@ static void group_chat_room_send_file (void) {
|
||||||
group_chat_room_send_file_with_or_without_text(FALSE);
|
group_chat_room_send_file_with_or_without_text(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void group_chat_room_send_file_plus_text(void) {
|
static void group_chat_room_send_file_plus_text (void) {
|
||||||
group_chat_room_send_file_with_or_without_text(TRUE);
|
group_chat_room_send_file_with_or_without_text(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void group_chat_room_unique_one_to_one_chat_room (void) {
|
||||||
|
LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc");
|
||||||
|
LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc");
|
||||||
|
bctbx_list_t *coresManagerList = NULL;
|
||||||
|
bctbx_list_t *participantsAddresses = NULL;
|
||||||
|
coresManagerList = bctbx_list_append(coresManagerList, marie);
|
||||||
|
coresManagerList = bctbx_list_append(coresManagerList, pauline);
|
||||||
|
bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
|
||||||
|
start_core_for_conference(coresManagerList);
|
||||||
|
participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc)));
|
||||||
|
stats initialMarieStats = marie->stat;
|
||||||
|
stats initialPaulineStats = pauline->stat;
|
||||||
|
|
||||||
|
// Marie creates a new group chat room
|
||||||
|
const char *initialSubject = "Pauline";
|
||||||
|
LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1);
|
||||||
|
BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne);
|
||||||
|
|
||||||
|
LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr));
|
||||||
|
|
||||||
|
// Check that the chat room is correctly created on Pauline's side and that the participants are added
|
||||||
|
LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, 0);
|
||||||
|
BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne);
|
||||||
|
|
||||||
|
// Marie sends a message
|
||||||
|
const char *message = "Hello";
|
||||||
|
_send_message(marieCr, message);
|
||||||
|
BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 10000));
|
||||||
|
BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 10000));
|
||||||
|
BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), message);
|
||||||
|
|
||||||
|
// Marie deletes the chat room
|
||||||
|
linphone_core_manager_delete_chat_room(marie, marieCr, coresList);
|
||||||
|
|
||||||
|
// Marie creates the chat room again
|
||||||
|
initialMarieStats = marie->stat;
|
||||||
|
initialPaulineStats = pauline->stat;
|
||||||
|
participantsAddresses = bctbx_list_append(NULL, linphone_address_new(linphone_core_get_identity(pauline->lc)));
|
||||||
|
marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1);
|
||||||
|
|
||||||
|
// Marie sends a new message
|
||||||
|
message = "Hey again";
|
||||||
|
_send_message(marieCr, message);
|
||||||
|
BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 10000));
|
||||||
|
BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 10000));
|
||||||
|
BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), message);
|
||||||
|
|
||||||
|
// Check that the created address is the same as before
|
||||||
|
const LinphoneAddress *newConfAddr = linphone_chat_room_get_conference_address(marieCr);
|
||||||
|
BC_ASSERT_TRUE(linphone_address_weak_equal(confAddr, newConfAddr));
|
||||||
|
|
||||||
|
// Clean db from chat room
|
||||||
|
linphone_core_manager_delete_chat_room(marie, marieCr, coresList);
|
||||||
|
linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList);
|
||||||
|
|
||||||
|
linphone_address_unref(confAddr);
|
||||||
|
bctbx_list_free(coresList);
|
||||||
|
bctbx_list_free(coresManagerList);
|
||||||
|
linphone_core_manager_destroy(marie);
|
||||||
|
linphone_core_manager_destroy(pauline);
|
||||||
|
}
|
||||||
|
|
||||||
test_t group_chat_tests[] = {
|
test_t group_chat_tests[] = {
|
||||||
TEST_TWO_TAGS("Group chat room creation server", group_chat_room_creation_server, "Server", "LeaksMemory"),
|
TEST_TWO_TAGS("Group chat room creation server", group_chat_room_creation_server, "Server", "LeaksMemory"),
|
||||||
TEST_TWO_TAGS("Send message", group_chat_room_send_message, "Server", "LeaksMemory"),
|
TEST_TWO_TAGS("Send message", group_chat_room_send_message, "Server", "LeaksMemory"),
|
||||||
|
|
@ -2062,7 +2127,8 @@ test_t group_chat_tests[] = {
|
||||||
TEST_TWO_TAGS("Migrate basic chat room to client group chat room failure", group_chat_room_migrate_from_basic_to_client_fail, "Server", "LeaksMemory"),
|
TEST_TWO_TAGS("Migrate basic chat room to client group chat room failure", group_chat_room_migrate_from_basic_to_client_fail, "Server", "LeaksMemory"),
|
||||||
TEST_TWO_TAGS("Migrate basic chat room to client group chat room not needed", group_chat_donot_room_migrate_from_basic_chat_room, "Server", "LeaksMemory"),
|
TEST_TWO_TAGS("Migrate basic chat room to client group chat room not needed", group_chat_donot_room_migrate_from_basic_chat_room, "Server", "LeaksMemory"),
|
||||||
TEST_TWO_TAGS("Send file", group_chat_room_send_file, "Server", "LeaksMemory"),
|
TEST_TWO_TAGS("Send file", group_chat_room_send_file, "Server", "LeaksMemory"),
|
||||||
TEST_TWO_TAGS("Send file + text", group_chat_room_send_file_plus_text, "Server", "LeaksMemory")
|
TEST_TWO_TAGS("Send file + text", group_chat_room_send_file_plus_text, "Server", "LeaksMemory"),
|
||||||
|
TEST_TWO_TAGS("Unique one-to-one chatroom", group_chat_room_unique_one_to_one_chat_room, "Server", "LeaksMemory")
|
||||||
};
|
};
|
||||||
|
|
||||||
test_suite_t group_chat_test_suite = {
|
test_suite_t group_chat_test_suite = {
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,7 @@ typedef struct _stats {
|
||||||
int number_of_LinphoneChatRoomStateTerminationPending;
|
int number_of_LinphoneChatRoomStateTerminationPending;
|
||||||
int number_of_LinphoneChatRoomStateTerminated;
|
int number_of_LinphoneChatRoomStateTerminated;
|
||||||
int number_of_LinphoneChatRoomStateCreationFailed;
|
int number_of_LinphoneChatRoomStateCreationFailed;
|
||||||
|
int number_of_LinphoneChatRoomStateDeleted;
|
||||||
|
|
||||||
int number_of_IframeDecoded;
|
int number_of_IframeDecoded;
|
||||||
|
|
||||||
|
|
@ -331,6 +332,7 @@ void linphone_core_manager_restart(LinphoneCoreManager *mgr, bool_t check_for_pr
|
||||||
void linphone_core_manager_uninit(LinphoneCoreManager *mgr);
|
void linphone_core_manager_uninit(LinphoneCoreManager *mgr);
|
||||||
void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr);
|
void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr);
|
||||||
void linphone_core_manager_destroy(LinphoneCoreManager* mgr);
|
void linphone_core_manager_destroy(LinphoneCoreManager* mgr);
|
||||||
|
void linphone_core_manager_delete_chat_room (LinphoneCoreManager *mgr, LinphoneChatRoom *cr, bctbx_list_t *coresList);
|
||||||
|
|
||||||
void reset_counters( stats* counters);
|
void reset_counters( stats* counters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,12 @@ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) {
|
||||||
ms_free(mgr);
|
ms_free(mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void linphone_core_manager_delete_chat_room (LinphoneCoreManager *mgr, LinphoneChatRoom *cr, bctbx_list_t *coresList) {
|
||||||
|
stats mgrStats = mgr->stat;
|
||||||
|
linphone_core_delete_chat_room(mgr->lc, cr);
|
||||||
|
BC_ASSERT_TRUE(wait_for_list(coresList, &mgr->stat.number_of_LinphoneChatRoomStateDeleted, mgrStats.number_of_LinphoneChatRoomStateDeleted + 1, 10000));
|
||||||
|
}
|
||||||
|
|
||||||
int liblinphone_tester_ipv6_available(void){
|
int liblinphone_tester_ipv6_available(void){
|
||||||
if (liblinphonetester_ipv6) {
|
if (liblinphonetester_ipv6) {
|
||||||
struct addrinfo *ai=bctbx_ip_address_to_addrinfo(AF_INET6,SOCK_STREAM,"2a01:e00::2",53);
|
struct addrinfo *ai=bctbx_ip_address_to_addrinfo(AF_INET6,SOCK_STREAM,"2a01:e00::2",53);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue