From 24e4b233d9ca387eeeb79e49d8e0207826ce95a0 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 9 Oct 2017 12:06:22 +0200 Subject: [PATCH] Handle joining an existing group chat room when receiving a REFER inviting us to join. --- coreapi/callbacks.c | 17 ++++++++++++----- coreapi/chat.c | 12 +++++++++++- coreapi/private.h | 4 +++- src/c-wrapper/api/c-chat-room.cpp | 13 +++++-------- src/chat/basic-chat-room.cpp | 8 +++++++- src/chat/basic-chat-room.h | 1 + src/chat/client-group-chat-room.cpp | 14 ++++++++++++-- src/chat/client-group-chat-room.h | 3 ++- src/chat/real-time-text-chat-room.cpp | 8 +++++++- src/chat/real-time-text-chat-room.h | 1 + src/conference/conference-interface.h | 1 + src/conference/conference.cpp | 11 +++++++++-- src/conference/conference.h | 3 ++- src/conference/local-conference.cpp | 1 - src/conference/session/call-session.h | 1 + 15 files changed, 74 insertions(+), 24 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 3e89c1b60..f2d3aaa71 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -715,11 +715,18 @@ static void on_notify_response(SalOp *op){ } static void refer_received(SalOp *op, const SalAddress *refer_to){ - /*if processing is ok*/ - dynamic_cast(op)->reply(SalReasonNone); - - /*otherwise*/ - //dynamic_cast(op)->reply(SalReasonDeclined); + if (sal_address_has_param(refer_to, "text")) { + LinphonePrivate::Address addr(sal_address_as_string(refer_to)); + if (addr.isValid()) { + LinphoneCore *lc = reinterpret_cast(op->get_sal()->get_user_pointer()); + LinphoneChatRoom *cr = _linphone_core_join_client_group_chat_room(lc, addr); + if (cr) { + static_cast(op)->reply(SalReasonNone); + return; + } + } + } + static_cast(op)->reply(SalReasonDeclined); } Sal::Callbacks linphone_sal_callbacks={ diff --git a/coreapi/chat.c b/coreapi/chat.c index eab5ed37e..daf9b7bb6 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -127,7 +127,17 @@ LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAd } LinphoneChatRoom * linphone_core_create_client_group_chat_room(LinphoneCore *lc, const char *subject) { - LinphoneChatRoom *cr = _linphone_client_group_chat_room_new(lc, subject); + const char *factoryUri = linphone_core_get_conference_factory_uri(lc); + if (!factoryUri) + return nullptr; + LinphoneChatRoom *cr = _linphone_client_group_chat_room_new(lc, factoryUri, subject); + lc->chatrooms = bctbx_list_append(lc->chatrooms, cr); + return cr; +} + +LinphoneChatRoom *_linphone_core_join_client_group_chat_room (LinphoneCore *lc, const LinphonePrivate::Address &addr) { + LinphoneChatRoom *cr = _linphone_client_group_chat_room_new(lc, addr.asString().c_str(), nullptr); + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->join(); lc->chatrooms = bctbx_list_append(lc->chatrooms, cr); return cr; } diff --git a/coreapi/private.h b/coreapi/private.h index 325be8645..31bbda276 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -31,6 +31,7 @@ #include "linphone/tunnel.h" #include "linphone/core_utils.h" #include "linphone/conference.h" +#include "address/address.h" #include "c-wrapper/internal/c-sal.h" #include "sal/call-op.h" #include "sal/event-op.h" @@ -462,7 +463,8 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj); /*chat*/ LinphoneChatRoom * linphone_chat_room_new(LinphoneCore *core, const LinphoneAddress *addr); -LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, const char *subject); +LinphoneChatRoom *_linphone_core_join_client_group_chat_room (LinphoneCore *core, const LinphonePrivate::Address &addr); +LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, const char *uri, const char *subject); void linphone_chat_room_release(LinphoneChatRoom *cr); void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call); bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr); diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index 26eb20ee9..163681be0 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -300,13 +300,10 @@ LinphoneChatRoom *linphone_chat_room_new (LinphoneCore *core, const LinphoneAddr return cr; } -LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, const char *subject) { - const char *factoryUri = linphone_core_get_conference_factory_uri(core); - if (!factoryUri) - return nullptr; - LinphoneAddress *factoryAddr = linphone_address_new(factoryUri); - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, factoryAddr); - linphone_address_unref(factoryAddr); +LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, const char *uri, const char *subject) { + LinphoneAddress *addr = linphone_address_new(uri); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, addr); + linphone_address_unref(addr); string from; if (proxy) from = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_proxy_config_get_identity_address(proxy))->asString(); @@ -314,7 +311,7 @@ LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, cons from = linphone_core_get_primary_contact(core); LinphonePrivate::Address me(from); LinphoneChatRoom *cr = L_INIT(ChatRoom); - L_SET_CPP_PTR_FROM_C_OBJECT(cr, LinphonePrivate::ObjectFactory::create(core, me, L_C_TO_STRING(subject))); + L_SET_CPP_PTR_FROM_C_OBJECT(cr, LinphonePrivate::ObjectFactory::create(core, me, L_C_TO_STRING(uri), L_C_TO_STRING(subject))); L_GET_PRIVATE_FROM_C_OBJECT(cr)->setState(LinphonePrivate::ChatRoom::State::Instantiated); return cr; } diff --git a/src/chat/basic-chat-room.cpp b/src/chat/basic-chat-room.cpp index 769abf5d9..f0eaacc66 100644 --- a/src/chat/basic-chat-room.cpp +++ b/src/chat/basic-chat-room.cpp @@ -69,7 +69,13 @@ const string &BasicChatRoom::getSubject () const { return d->subject; } -void BasicChatRoom::leave () {} +void BasicChatRoom::join () { + lError() << "join() is not allowed on a BasicChatRoom"; +} + +void BasicChatRoom::leave () { + lError() << "leave() is not allowed on a BasicChatRoom"; +} void BasicChatRoom::removeParticipant (const shared_ptr &participant) { lError() << "removeParticipant() is not allowed on a BasicChatRoom"; diff --git a/src/chat/basic-chat-room.h b/src/chat/basic-chat-room.h index 62c15c849..bd693e83b 100644 --- a/src/chat/basic-chat-room.h +++ b/src/chat/basic-chat-room.h @@ -41,6 +41,7 @@ public: int getNbParticipants () const override; std::list> getParticipants () const override; const std::string &getSubject () const override; + void join () override; void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; diff --git a/src/chat/client-group-chat-room.cpp b/src/chat/client-group-chat-room.cpp index 4966fcee0..3b98f9448 100644 --- a/src/chat/client-group-chat-room.cpp +++ b/src/chat/client-group-chat-room.cpp @@ -52,9 +52,9 @@ shared_ptr ClientGroupChatRoomPrivate::createSession () { // ============================================================================= -ClientGroupChatRoom::ClientGroupChatRoom (LinphoneCore *core, const Address &me, const string &subject) +ClientGroupChatRoom::ClientGroupChatRoom (LinphoneCore *core, const Address &me, const string &uri, const string &subject) : ChatRoom(*new ClientGroupChatRoomPrivate(core)), RemoteConference(core, me, nullptr) { - focus = ObjectFactory::create(Address(linphone_core_get_conference_factory_uri(core))); + focus = ObjectFactory::create(Address(uri)); this->subject = subject; } @@ -113,6 +113,16 @@ const string &ClientGroupChatRoom::getSubject () const { return RemoteConference::getSubject(); } +void ClientGroupChatRoom::join () { + L_D(); + shared_ptr session = focus->getPrivate()->getSession(); + if (!session && (d->state == ChatRoom::State::Instantiated)) { + session = d->createSession(); + session->startInvite(nullptr, "", nullptr); + d->setState(ChatRoom::State::CreationPending); + } +} + void ClientGroupChatRoom::leave () { L_D(); eventHandler->unsubscribe(); diff --git a/src/chat/client-group-chat-room.h b/src/chat/client-group-chat-room.h index eaf212f52..1d28aa825 100644 --- a/src/chat/client-group-chat-room.h +++ b/src/chat/client-group-chat-room.h @@ -37,7 +37,7 @@ class ClientGroupChatRoomPrivate; class LINPHONE_PUBLIC ClientGroupChatRoom : public ChatRoom, public RemoteConference { public: - ClientGroupChatRoom (LinphoneCore *core, const Address &me, const std::string &subject); + ClientGroupChatRoom (LinphoneCore *core, const Address &me, const std::string &uri, const std::string &subject); virtual ~ClientGroupChatRoom () = default; public: @@ -49,6 +49,7 @@ public: int getNbParticipants () const override; std::list> getParticipants () const override; const std::string &getSubject () const override; + void join () override; void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; diff --git a/src/chat/real-time-text-chat-room.cpp b/src/chat/real-time-text-chat-room.cpp index f29a70fea..d89e6befe 100644 --- a/src/chat/real-time-text-chat-room.cpp +++ b/src/chat/real-time-text-chat-room.cpp @@ -165,7 +165,13 @@ const string &RealTimeTextChatRoom::getSubject () const { return d->subject; } -void RealTimeTextChatRoom::leave () {} +void RealTimeTextChatRoom::join () { + lError() << "join() is not allowed on a RealTimeTextChatRoom"; +} + +void RealTimeTextChatRoom::leave () { + lError() << "leave() is not allowed on a RealTimeTextChatRoom"; +} void RealTimeTextChatRoom::removeParticipant (const shared_ptr &participant) { lError() << "removeParticipant() is not allowed on a RealTimeTextChatRoom"; diff --git a/src/chat/real-time-text-chat-room.h b/src/chat/real-time-text-chat-room.h index 9eacb9e3d..ec7bdf929 100644 --- a/src/chat/real-time-text-chat-room.h +++ b/src/chat/real-time-text-chat-room.h @@ -51,6 +51,7 @@ public: int getNbParticipants () const override; std::list> getParticipants () const override; const std::string &getSubject () const override; + void join () override; void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; diff --git a/src/conference/conference-interface.h b/src/conference/conference-interface.h index 0829df832..a1d187991 100644 --- a/src/conference/conference-interface.h +++ b/src/conference/conference-interface.h @@ -42,6 +42,7 @@ public: virtual int getNbParticipants () const = 0; virtual std::list> getParticipants () const = 0; virtual const std::string &getSubject () const = 0; + virtual void join () = 0; virtual void leave () = 0; virtual void removeParticipant (const std::shared_ptr &participant) = 0; virtual void removeParticipants (const std::list> &participants) = 0; diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp index d6e626088..9794b706c 100644 --- a/src/conference/conference.cpp +++ b/src/conference/conference.cpp @@ -20,6 +20,7 @@ #include "participant-p.h" #include "conference.h" +#include "conference/session/call-session-p.h" #include "logger/logger.h" using namespace std; @@ -76,6 +77,8 @@ const string &Conference::getSubject () const { return subject; } +void Conference::join () {} + void Conference::leave () {} void Conference::removeParticipant (const shared_ptr &participant) { @@ -166,14 +169,18 @@ void Conference::onResetFirstVideoFrameDecoded (const std::shared_ptr Conference::findParticipant (const Address &addr) const { + Address testedAddr = addr; + testedAddr.setPort(0); for (const auto &participant : participants) { - if (addr.equal(participant->getAddress())) + Address participantAddr = participant->getAddress(); + participantAddr.setPort(0); + if (testedAddr.equal(participantAddr)) return participant; } return nullptr; } -shared_ptr Conference::findParticipant (const shared_ptr &session) { +shared_ptr Conference::findParticipant (const shared_ptr &session) const { for (const auto &participant : participants) { if (participant->getPrivate()->getSession() == session) return participant; diff --git a/src/conference/conference.h b/src/conference/conference.h index 2ee2c452d..1d30d0b80 100644 --- a/src/conference/conference.h +++ b/src/conference/conference.h @@ -55,6 +55,7 @@ public: int getNbParticipants () const override; std::list> getParticipants () const override; const std::string &getSubject () const override; + void join () override; void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; @@ -81,7 +82,7 @@ protected: explicit Conference (LinphoneCore *core, const Address &myAddress, CallListener *listener = nullptr); std::shared_ptr findParticipant (const Address &addr) const; - std::shared_ptr findParticipant (const std::shared_ptr &session); + std::shared_ptr findParticipant (const std::shared_ptr &session) const; bool isMe (const Address &addr) const ; protected: diff --git a/src/conference/local-conference.cpp b/src/conference/local-conference.cpp index 07b026aa8..1a1dcc07b 100644 --- a/src/conference/local-conference.cpp +++ b/src/conference/local-conference.cpp @@ -44,7 +44,6 @@ void LocalConference::addParticipant (const Address &addr, const CallSessionPara if (participant) return; participant = ObjectFactory::create(addr); - participant->getPrivate()->createSession(*this, params, hasMedia, this); participants.push_back(participant); if (!activeParticipant) activeParticipant = participant; diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index 3f32d5813..c0eaccc8b 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -39,6 +39,7 @@ class LINPHONE_PUBLIC CallSession : public Object { friend class CallPrivate; friend class ClientGroupChatRoom; friend class ClientGroupChatRoomPrivate; + friend class Conference; public: L_OVERRIDE_SHARED_FROM_THIS(CallSession);