Commit 359b7bde authored by Ghislain MARY's avatar Ghislain MARY

Handle one-to-one chat rooms and quit the client group chat room when deleting it.

parent 1e350eda
......@@ -80,11 +80,30 @@ static void call_received(SalCallOp *h) {
LinphoneAddress *toAddr = linphone_address_new(h->get_to());
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(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;
} 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(
......
......@@ -92,7 +92,7 @@ LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc
}
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) {
......
......@@ -29,13 +29,15 @@
F(Created) \
F(TerminationPending) \
F(Terminated) \
F(CreationFailed)
F(CreationFailed) \
F(Deleted)
#define L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES(F) \
F(Basic, 1 << 0) \
F(RealTimeText, 1 << 1) \
F(Conference, 1 << 2) \
F(Proxy, 1 << 3) \
F(Migratable, 1 << 4)
F(Migratable, 1 << 4) \
F(OneToOne, 1 << 5)
#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 ChatMessagePrivate;
friend class ClientGroupToBasicChatRoomPrivate;
friend class Core;
friend class CorePrivate;
friend class MainDb;
friend class ProxyChatRoomPrivate;
......@@ -66,6 +67,7 @@ public:
virtual std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const = 0;
virtual int getHistorySize () const = 0;
virtual void deleteFromDb () = 0;
virtual void deleteHistory () = 0;
virtual std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const = 0;
......
......@@ -346,6 +346,12 @@ int ChatRoom::getHistorySize () const {
return getCore()->getPrivate()->mainDb->getHistorySize(getChatRoomId());
}
void ChatRoom::deleteFromDb () {
L_D();
Core::deleteChatRoom(this->getSharedFromThis());
d->setState(ChatRoom::State::Deleted);
}
void ChatRoom::deleteHistory () {
getCore()->getPrivate()->mainDb->cleanHistory(getChatRoomId());
}
......
......@@ -46,6 +46,7 @@ public:
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
int getHistorySize () const override;
void deleteFromDb () override;
void deleteHistory () override;
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
......
......@@ -42,6 +42,7 @@ public:
// ChatRoomListener
void onChatRoomInsertRequested (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
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override;
......@@ -50,6 +51,8 @@ public:
private:
CallSessionListener *callSessionListener = this;
ChatRoomListener *chatRoomListener = this;
ClientGroupChatRoom::CapabilitiesMask capabilities = ClientGroupChatRoom::Capabilities::Conference;
bool deletionOnTerminationEnabled = false;
L_DECLARE_PUBLIC(ClientGroupChatRoom);
};
......
......@@ -62,6 +62,8 @@ shared_ptr<CallSession> ClientGroupChatRoomPrivate::createSession () {
CallSessionParams csp;
csp.addCustomHeader("Require", "recipient-list-invite");
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<CallSession> session = focus->getPrivate()->createSession(*q, &csp, false, callSessionListener);
......@@ -111,6 +113,12 @@ void ClientGroupChatRoomPrivate::onChatRoomInsertInDatabaseRequested (const shar
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) {
......@@ -164,6 +172,7 @@ ClientGroupChatRoom::ClientGroupChatRoom (
const shared_ptr<Core> &core,
const ChatRoomId &chatRoomId,
shared_ptr<Participant> &me,
AbstractChatRoom::CapabilitiesMask capabilities,
const string &subject,
list<shared_ptr<Participant>> &&participants,
unsigned int lastNotifyId
......@@ -189,7 +198,8 @@ shared_ptr<Core> ClientGroupChatRoom::getCore () const {
}
ClientGroupChatRoom::CapabilitiesMask ClientGroupChatRoom::getCapabilities () const {
return Capabilities::Conference;
L_D();
return d->capabilities;
}
bool ClientGroupChatRoom::hasBeenLeft () const {
......@@ -208,6 +218,16 @@ const IdentityAddress &ClientGroupChatRoom::getConferenceAddress () const {
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) {
list<IdentityAddress> addresses;
addresses.push_back(addr);
......@@ -231,6 +251,19 @@ void ClientGroupChatRoom::addParticipants (
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.setBody(getResourceLists(addressesList));
content.setContentType("application/resource-lists+xml");
......@@ -372,6 +405,11 @@ void ClientGroupChatRoom::onConferenceCreated (const IdentityAddress &addr) {
d->chatRoomListener->onChatRoomInsertRequested(getSharedFromThis());
}
void ClientGroupChatRoom::onConferenceKeywordsChanged (const vector<string> &keywords) {
L_D();
d->capabilities |= ClientGroupChatRoom::Capabilities::OneToOne;
}
void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) {
L_D();
L_D_T(RemoteConference, dConference);
......@@ -382,6 +420,10 @@ void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) {
time(nullptr),
d->chatRoomId
));
if (d->deletionOnTerminationEnabled) {
d->deletionOnTerminationEnabled = false;
d->chatRoomListener->onChatRoomDeleteRequested(getSharedFromThis());
}
}
void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) {
......
......@@ -32,6 +32,7 @@ class ClientGroupChatRoomPrivate;
class LINPHONE_PUBLIC ClientGroupChatRoom : public ChatRoom, public RemoteConference {
friend class BasicToClientGroupChatRoomPrivate;
friend class ClientGroupToBasicChatRoomPrivate;
friend class Core;
public:
L_OVERRIDE_SHARED_FROM_THIS(ClientGroupChatRoom);
......@@ -48,6 +49,7 @@ public:
const std::shared_ptr<Core> &core,
const ChatRoomId &chatRoomId,
std::shared_ptr<Participant> &me,
AbstractChatRoom::CapabilitiesMask capabilities,
const std::string &subject,
std::list<std::shared_ptr<Participant>> &&participants,
unsigned int lastNotifyId
......@@ -63,6 +65,8 @@ public:
bool canHandleParticipants () const override;
bool canHandleCpim () const override;
void deleteFromDb () 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;
......@@ -88,6 +92,7 @@ private:
// ALL METHODS AFTER THIS POINT.
void onConferenceCreated (const IdentityAddress &addr) override;
void onConferenceKeywordsChanged (const std::vector<std::string> &keywords) override;
void onConferenceTerminated (const IdentityAddress &addr) override;
void onFirstNotifyReceived (const IdentityAddress &addr) override;
void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) override;
......
......@@ -46,6 +46,12 @@ public:
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 {
if (!(chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference))
return;
......
......@@ -190,6 +190,11 @@ int ProxyChatRoom::getHistorySize () const {
return d->chatRoom->getHistorySize();
}
void ProxyChatRoom::deleteFromDb () {
L_D();
d->chatRoom->deleteFromDb();
}
void ProxyChatRoom::deleteHistory () {
L_D();
d->chatRoom->deleteHistory();
......
......@@ -47,6 +47,7 @@ public:
std::list<std::shared_ptr<EventLog>> getHistoryRange (int begin, int end) const override;
int getHistorySize () const override;
void deleteFromDb () override;
void deleteHistory () override;
std::shared_ptr<ChatMessage> getLastChatMessageInHistory () const override;
......
......@@ -35,6 +35,7 @@ public:
void confirmCreation ();
void confirmJoining (SalCallOp *op);
void confirmRecreation (SalCallOp *op);
IdentityAddress generateConferenceAddress (const std::shared_ptr<Participant> &me) const;
......@@ -43,10 +44,9 @@ public:
void update (SalCallOp *op);
void dispatchMessage (const IdentityAddress &fromAddress, const Content &content);
void setConferenceAddress (const IdentityAddress &conferenceAddress);
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;
......@@ -63,12 +63,14 @@ private:
// CallSessionListener
void onCallSessionStateChanged (
const std::shared_ptr<const CallSession> &session,
CallSession::State state,
CallSession::State newState,
const std::string &message
) override;
std::list<std::shared_ptr<Participant>> removedParticipants;
ChatRoomListener *chatRoomListener = this;
ServerGroupChatRoom::CapabilitiesMask capabilities = ServerGroupChatRoom::Capabilities::Conference;
bool joiningPendingAfterCreation = false;
L_DECLARE_PUBLIC(ServerGroupChatRoom);
};
......
......@@ -46,6 +46,8 @@ void ServerGroupChatRoomPrivate::confirmCreation () {}
void ServerGroupChatRoomPrivate::confirmJoining (SalCallOp *) {}
void ServerGroupChatRoomPrivate::confirmRecreation (SalCallOp *) {}
// -----------------------------------------------------------------------------
IdentityAddress ServerGroupChatRoomPrivate::generateConferenceAddress (const shared_ptr<Participant> &me) const {
......@@ -110,6 +112,7 @@ LocalConference(core, IdentityAddress(op->get_to()), nullptr) {
ServerGroupChatRoom::ServerGroupChatRoom (
const shared_ptr<Core> &core,
const IdentityAddress &peerAddress,
AbstractChatRoom::CapabilitiesMask capabilities,
const string &subject,
list<shared_ptr<Participant>> &&participants,
unsigned int lastNotifyId
......
......@@ -39,11 +39,16 @@ public:
ServerGroupChatRoom (
const std::shared_ptr<Core> &core,
const IdentityAddress &peerAddress,
AbstractChatRoom::CapabilitiesMask capabilities,
const std::string &subject,
std::list<std::shared_ptr<Participant>> &&participants,
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;
bool hasBeenLeft () const override;
......
......@@ -22,6 +22,7 @@
#include <ctime>
#include <string>
#include <vector>
#include "linphone/utils/general.h"
......@@ -36,6 +37,7 @@ class IdentityAddress;
class ConferenceListener {
public:
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 onFirstNotifyReceived (const IdentityAddress &addr) = 0;
virtual void onParticipantAdded (const std::shared_ptr<ConferenceParticipantEvent> &event, bool isFullState) = 0;
......
......@@ -37,7 +37,7 @@ public:
void notifyFullState (const std::string &notify, const std::shared_ptr<ParticipantDevice> &device);
void notifyAllExcept (const std::string &notify, const std::shared_ptr<Participant> &exceptParticipant);
void notifyAll (const std::string &notify);
std::string createNotifyFullState (int notifyId = -1);
std::string createNotifyFullState (int notifyId = -1, bool oneToOne = false);
std::string createNotifyMultipart (int notifyId);
std::string createNotifyParticipantAdded (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();
}
string LocalConferenceEventHandlerPrivate::createNotifyFullState (int notifyId) {
string LocalConferenceEventHandlerPrivate::createNotifyFullState (int notifyId, bool oneToOne) {
string entity = conf->getConferenceAddress().asString();
string subject = conf->getSubject();
ConferenceType confInfo = ConferenceType(entity);
UsersType users;
ConferenceDescriptionType confDescr = ConferenceDescriptionType();
confDescr.setSubject(subject);
if (oneToOne) {
KeywordsType keywords(sizeof(char), "one-to-one");
confDescr.setKeywords(keywords);
}
confInfo.setUsers(users);
confInfo.setConferenceDescription((const ConferenceDescriptionType) confDescr);
......@@ -357,18 +361,13 @@ string LocalConferenceEventHandlerPrivate::createNotifyParticipantDeviceRemoved
LocalConferenceEventHandler::LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify) :
Object(*new LocalConferenceEventHandlerPrivate) {
L_D();
xercesc::XMLPlatformUtils::Initialize();
d->conf = localConference;
d->lastNotify = notify;
}
LocalConferenceEventHandler::~LocalConferenceEventHandler () {
xercesc::XMLPlatformUtils::Terminate();
}
// -----------------------------------------------------------------------------
void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev) {
void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev, bool oneToOne) {
L_D();
const LinphoneAddress *lAddr = linphone_event_get_from(lev);
char *addrStr = linphone_address_as_string(lAddr);
......@@ -396,7 +395,7 @@ void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev) {
device->setConferenceSubscribeEvent(lev);
if (lastNotify == 0) {
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) {
lInfo() << "Sending all missed notify [" << lastNotify << "-" << d->lastNotify <<
"] for conference:" << d->conf->getConferenceAddress().asString() <<
......
......@@ -42,9 +42,8 @@ class LocalConferenceEventHandlerPrivate;
class LocalConferenceEventHandler : public Object {
public:
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> notifyParticipantRemoved (const Address &addr);
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.
*/
#include <sstream>
#include "linphone/utils/utils.h"
#include "conference/remote-conference.h"
......@@ -53,20 +55,30 @@ void RemoteConferenceEventHandlerPrivate::simpleNotifyReceived (const string &xm
IdentityAddress entityAddress(confInfo->getEntity().c_str());
if (entityAddress == chatRoomId.getPeerAddress()) {
if (
confInfo->getConferenceDescription().present() &&
confInfo->getConferenceDescription().get().getSubject().present() &&
!confInfo->getConferenceDescription().get().getSubject().get().empty()
)
confListener->onSubjectChanged(
make_shared<ConferenceSubjectEvent>(
tm,
chatRoomId,
lastNotify,
confInfo->getConferenceDescription().get().getSubject().get()
),
isFullState
);
if (confInfo->getConferenceDescription().present()) {
if (confInfo->getConferenceDescription().get().getSubject().present() &&
!confInfo->getConferenceDescription().get().getSubject().get().empty()
) {
confListener->onSubjectChanged(
make_shared<ConferenceSubjectEvent>(
tm,
chatRoomId,
lastNotify,
confInfo->getConferenceDescription().get().getSubject().get()
),
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())
lastNotify = confInfo->getVersion().get();
......@@ -215,7 +227,6 @@ void RemoteConferenceEventHandlerPrivate::onRegistrationStateChanged (LinphonePr
RemoteConferenceEventHandler::RemoteConferenceEventHandler (RemoteConference *remoteConference) :
Object(*new RemoteConferenceEventHandlerPrivate) {
L_D();
xercesc::XMLPlatformUtils::Initialize();
d->conf = remoteConference;
d->conf->getCore()->getPrivate()->registerListener(d);
}
......@@ -223,7 +234,6 @@ Object(*new RemoteConferenceEventHandlerPrivate) {
RemoteConferenceEventHandler::~RemoteConferenceEventHandler () {
L_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.
*/
#include "content/content.h"
#include "content/content-type.h"
#include "handlers/local-conference-event-handler.h"
#include "local-conference-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) {
istringstream data(xmlBody);
unique_ptr<Xsd::ResourceLists::ResourceLists> rl = LinphonePrivate::Xsd::ResourceLists::parseResourceLists(
data,
Xsd::XmlSchema::Flags::dont_validate
);
list<IdentityAddress> addresses = list<IdentityAddress>();
for (const auto &l : rl->getList()) {
for (const auto &entry : l.getEntry()) {
IdentityAddress addr(entry.getUri());
addresses.push_back(addr);
list<IdentityAddress> LocalConference::parseResourceLists (const Content &content) {
if ((content.getContentType() == ContentType::ResourceLists)
&& (content.getContentDisposition() == "recipient-list")
) {
istringstream data(content.getBodyAsString());
unique_ptr<Xsd::ResourceLists::ResourceLists> rl(Xsd::ResourceLists::parseResourceLists(
data,
Xsd::XmlSchema::Flags::dont_validate
));
list<IdentityAddress> addresses;
for (const auto &l : rl->getList()) {
for (const auto &entry : l.getEntry()) {
IdentityAddress addr(entry.getUri());
addresses.push_back(move(addr));
}
}
return addresses;
}
return addresses;
return list<IdentityAddress>();
}
LINPHONE_END_NAMESPACE
......@@ -26,6 +26,7 @@
LINPHONE_BEGIN_NAMESPACE
class Content;
class LocalConferencePrivate;
class LocalConference : public Conference {
......@@ -39,7 +40,7 @@ public:
void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) 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:
L_DECLARE_PRIVATE(LocalConference);
......
......@@ -252,21 +252,12 @@ void Core::deleteChatRoom (const shared_ptr<const AbstractChatRoom> &chatRoom) {
CorePrivate *d = chatRoom->getCore()->getPrivate();
const ChatRoomId &chatRoomId = chatRoom->getChatRoomId();
auto it = d->chatRoomsById.find(chatRoomId);
if (it != d->chatRoomsById.end()) {
// TODO: Remove me later.
auto it = find_if(
d->chatRooms.begin(), d->chatRooms.end(),
[&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);
auto chatRoomsByIdIt = d->chatRoomsById.find(chatRoomId);
if (chatRoomsByIdIt != d->chatRoomsById.end()) {
auto chatRoomsIt = find(d->chatRooms.begin(), d->chatRooms.end(), chatRoom);
L_ASSERT(chatRoomsIt != d->chatRooms.end());
d->chatRooms.erase(chatRoomsIt);
d->chatRoomsById.erase(chatRoomsByIdIt);
d->mainDb->deleteChatRoom(chatRoomId);
}
}
......
......@@ -18,6 +18,7 @@
*/
#include <mediastreamer2/mscommon.h>
#include <xercesc/util/PlatformUtils.hpp>
#include "call/call.h"
#include "core/core-listener.h"
......@@ -52,7 +53,7 @@ void CorePrivate::init () {
uri = q->getDataPath() + LINPHONE_DB;
}
lInfo() << "Opening " LINPHONE_DB "...";
lInfo() << "Opening linphone database: " << uri;
if (!mainDb->connect(backend, uri))
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 () {
lInfo() << "Destroying core: " << this;
xercesc::XMLPlatformUtils::Terminate();
}
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 (const ChatRoomId &chatRoomId) 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 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());
// Remove capabilities like `Proxy`.
const int &capabilities = chatRoom->getCapabilities() & ChatRoom::CapabilitiesMask({
ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::RealTimeText,
ChatRoom::Capabilities::Conference, ChatRoom::Capabilities::Migratable
});
const int &capabilities = chatRoom->getCapabilities() & ~ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Proxy);
const string &subject = chatRoom->getSubject();
const int &flags = chatRoom->hasBeenLeft();
......@@ -409,6 +406,18 @@ long long MainDbPrivate::selectChatRoomParticipantId (long long chatRoomId, long
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) {
......@@ -1372,6 +1381,26 @@ void MainDb::init () {
" ON DELETE CASCADE"
") " + 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 <<
"CREATE TABLE IF NOT EXISTS chat_room_participant ("
" id" + primaryKeyStr("BIGINT UNSIGNED") + ","