diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f2d3aaa71..9b49492b4 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sal/refer-op.h" #include "linphone/core.h" +#include "linphone/utils/utils.h" #include "private.h" #include "mediastreamer2/mediastream.h" #include "linphone/lpconfig.h" @@ -38,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "c-wrapper/c-wrapper.h" #include "call/call-p.h" +#include "chat/chat-room.h" #include "conference/session/call-session.h" #include "conference/session/call-session-p.h" #include "conference/session/media-session.h" @@ -719,10 +721,23 @@ static void refer_received(SalOp *op, const SalAddress *refer_to){ 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; + if (addr.hasParam("admin")) { + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, op->get_to()); + if (cr) { + std::shared_ptr participant = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findParticipant(addr); + if (participant) { + bool value = Utils::stob(addr.getParamValue("admin")); + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setParticipantAdminStatus(participant, value); + } + static_cast(op)->reply(SalReasonNone); + return; + } + } else { + LinphoneChatRoom *cr = _linphone_core_join_client_group_chat_room(lc, addr); + if (cr) { + static_cast(op)->reply(SalReasonNone); + return; + } } } } diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index ddadceb3e..e6e1d0d31 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -261,6 +261,13 @@ LINPHONE_PUBLIC void linphone_chat_room_add_participants (LinphoneChatRoom *cr, */ LINPHONE_PUBLIC bool_t linphone_chat_room_can_handle_participants (const LinphoneChatRoom *cr); +/** + * Find a participant of a chat room from its address. + * @param[in] cr A LinphoneChatRoom object + * @param[in] addr The address to search in the list of participants of the chat room + */ +LINPHONE_PUBLIC LinphoneParticipant *linphone_chat_room_find_participant (const LinphoneChatRoom *cr, const LinphoneAddress *addr); + /** * Get the conference address of the chat room. * @param[in] cr A LinphoneChatRoom object @@ -309,6 +316,14 @@ LINPHONE_PUBLIC void linphone_chat_room_remove_participant (LinphoneChatRoom *cr */ LINPHONE_PUBLIC void linphone_chat_room_remove_participants (LinphoneChatRoom *cr, const bctbx_list_t *participants); +/** + * Change the admin status of a participant of a chat room (you need to be an admin yourself to do this). + * @param[in] cr A LinphoneChatRoom object + * @param[in] participant The Participant for which to change the admin status + * @param[in] isAdmin A boolean value telling whether the participant should now be an admin or not + */ +LINPHONE_PUBLIC void linphone_chat_room_set_participant_admin_status (LinphoneChatRoom *cr, LinphoneParticipant *participant, bool_t isAdmin); + /** * Set the subject of a chat room. * @param[in] cr A LinphoneChatRoom object diff --git a/include/linphone/api/c-participant.h b/include/linphone/api/c-participant.h index bdc3054c4..21adf5f66 100644 --- a/include/linphone/api/c-participant.h +++ b/include/linphone/api/c-participant.h @@ -71,13 +71,6 @@ LINPHONE_PUBLIC const LinphoneAddress * linphone_participant_get_address (const */ LINPHONE_PUBLIC bool_t linphone_participant_is_admin (const LinphoneParticipant *participant); -/** - * Give the administrator rights or remove them to a conference participant. - * @param[in] participant A LinphoneParticipant object - * @param value A boolean value telling whether the participant should be an administrator or not - */ -LINPHONE_PUBLIC void linphone_participant_set_admin (LinphoneParticipant *participant, bool_t value); - /** * @} */ diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index 163681be0..e56d447c0 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -27,6 +27,7 @@ #include "chat/basic-chat-room.h" #include "chat/client-group-chat-room.h" #include "chat/real-time-text-chat-room-p.h" +#include "conference/participant.h" // ============================================================================= @@ -224,6 +225,10 @@ bool_t linphone_chat_room_can_handle_participants (const LinphoneChatRoom *cr) { return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->canHandleParticipants(); } +LinphoneParticipant *linphone_chat_room_find_participant (const LinphoneChatRoom *cr, const LinphoneAddress *addr) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findParticipant(*L_GET_CPP_PTR_FROM_C_OBJECT(addr))); +} + const LinphoneAddress *linphone_chat_room_get_conference_address (const LinphoneChatRoom *cr) { if (cr->conferenceAddressCache) { linphone_address_unref(cr->conferenceAddressCache); @@ -260,6 +265,11 @@ void linphone_chat_room_remove_participants (LinphoneChatRoom *cr, const bctbx_l L_GET_CPP_PTR_FROM_C_OBJECT(cr)->removeParticipants(L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(participants, Participant)); } +void linphone_chat_room_set_participant_admin_status (LinphoneChatRoom *cr, LinphoneParticipant *participant, bool_t isAdmin) { + shared_ptr p = L_GET_CPP_PTR_FROM_C_OBJECT(participant); + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setParticipantAdminStatus(p, !!isAdmin); +} + void linphone_chat_room_set_subject (LinphoneChatRoom *cr, const char *subject) { L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setSubject(L_C_TO_STRING(subject)); } diff --git a/src/c-wrapper/api/c-participant.cpp b/src/c-wrapper/api/c-participant.cpp index eb6c18814..783c92ca3 100644 --- a/src/c-wrapper/api/c-participant.cpp +++ b/src/c-wrapper/api/c-participant.cpp @@ -58,7 +58,3 @@ const LinphoneAddress *linphone_participant_get_address (const LinphoneParticipa bool_t linphone_participant_is_admin (const LinphoneParticipant *participant) { return L_GET_CPP_PTR_FROM_C_OBJECT(participant)->isAdmin(); } - -void linphone_participant_set_admin (LinphoneParticipant *participant, bool_t value) { - L_GET_CPP_PTR_FROM_C_OBJECT(participant)->setAdmin(!!value); -} diff --git a/src/chat/basic-chat-room.cpp b/src/chat/basic-chat-room.cpp index f0eaacc66..ae59ffd01 100644 --- a/src/chat/basic-chat-room.cpp +++ b/src/chat/basic-chat-room.cpp @@ -48,6 +48,11 @@ bool BasicChatRoom::canHandleParticipants () const { return false; } +shared_ptr BasicChatRoom::findParticipant (const Address &addr) const { + lError() << "findParticipant() is not allowed on a BasicChatRoom"; + return nullptr; +} + const Address *BasicChatRoom::getConferenceAddress () const { lError() << "a BasicChatRoom does not have a conference address"; return nullptr; @@ -85,6 +90,10 @@ void BasicChatRoom::removeParticipants (const list> &par lError() << "removeParticipants() is not allowed on a BasicChatRoom"; } +void BasicChatRoom::setParticipantAdminStatus (shared_ptr &participant, bool isAdmin) { + lError() << "setParticipantAdminStatus() is not allowed on a BasicChatRoom"; +} + void BasicChatRoom::setSubject (const string &subject) { L_D(); d->subject = subject; diff --git a/src/chat/basic-chat-room.h b/src/chat/basic-chat-room.h index bd693e83b..73b7ed78a 100644 --- a/src/chat/basic-chat-room.h +++ b/src/chat/basic-chat-room.h @@ -37,6 +37,7 @@ public: void addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) override; void addParticipants (const std::list
&addresses, const CallSessionParams *params, bool hasMedia) override; bool canHandleParticipants () const override; + std::shared_ptr findParticipant (const Address &addr) const override; const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; @@ -45,6 +46,7 @@ public: void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) override; void setSubject (const std::string &subject) override; private: diff --git a/src/chat/client-group-chat-room.cpp b/src/chat/client-group-chat-room.cpp index f261659bd..7abc13ad1 100644 --- a/src/chat/client-group-chat-room.cpp +++ b/src/chat/client-group-chat-room.cpp @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "linphone/utils/utils.h" + #include "address/address-p.h" #include "client-group-chat-room-p.h" #include "c-wrapper/c-wrapper.h" @@ -26,6 +28,7 @@ #include "content/content.h" #include "hacks/hacks.h" #include "logger/logger.h" +#include "sal/refer-op.h" // ============================================================================= @@ -103,6 +106,10 @@ bool ClientGroupChatRoom::canHandleParticipants () const { return RemoteConference::canHandleParticipants(); } +shared_ptr ClientGroupChatRoom::findParticipant (const Address &addr) const { + return RemoteConference::findParticipant(addr); +} + const Address *ClientGroupChatRoom::getConferenceAddress () const { return RemoteConference::getConferenceAddress(); } @@ -150,6 +157,27 @@ void ClientGroupChatRoom::removeParticipants (const list // TODO } +void ClientGroupChatRoom::setParticipantAdminStatus (shared_ptr &participant, bool isAdmin) { + L_D(); + if (isAdmin == participant->isAdmin()) + return; + if (!me->isAdmin()) { + lError() << "Cannot change the participant admin status because I am not admin"; + return; + } + SalReferOp *referOp = new SalReferOp(d->core->sal); + LinphoneAddress *lAddr = linphone_address_new(conferenceAddress.asString().c_str()); + linphone_configure_op(d->core, referOp, lAddr, nullptr, false); + linphone_address_unref(lAddr); + Address referToAddr = participant->getAddress(); + referToAddr.setParam("text"); + referToAddr.setParam("admin", Utils::toString(isAdmin)); + referToAddr.setDomain(""); + referToAddr.setPort(-1); + referOp->send_refer(referToAddr.getPrivate()->getInternalAddress()); + referOp->unref(); +} + void ClientGroupChatRoom::setSubject (const string &subject) { L_D(); if (d->state != ChatRoom::State::Created) { @@ -224,7 +252,7 @@ void ClientGroupChatRoom::onParticipantSetAdmin (const Address &addr, bool isAdm lWarning() << "Participant " << participant << " admin status has been changed but is not in the list of participants!"; return; } - participant->setAdmin(isAdmin); + participant->getPrivate()->setAdmin(isAdmin); LinphoneChatRoom *cr = L_GET_C_BACK_PTR(this); LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(cr); LinphoneChatRoomCbsParticipantAdminStatusChangedCb cb = linphone_chat_room_cbs_get_participant_admin_status_changed(cbs); diff --git a/src/chat/client-group-chat-room.h b/src/chat/client-group-chat-room.h index 1d28aa825..2d8692646 100644 --- a/src/chat/client-group-chat-room.h +++ b/src/chat/client-group-chat-room.h @@ -45,6 +45,7 @@ public: void addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) override; void addParticipants (const std::list
&addresses, const CallSessionParams *params, bool hasMedia) override; bool canHandleParticipants () const override; + std::shared_ptr findParticipant (const Address &addr) const override; const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; @@ -53,6 +54,7 @@ public: void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) override; void setSubject (const std::string &subject) override; private: diff --git a/src/chat/real-time-text-chat-room.cpp b/src/chat/real-time-text-chat-room.cpp index d89e6befe..2c71170d5 100644 --- a/src/chat/real-time-text-chat-room.cpp +++ b/src/chat/real-time-text-chat-room.cpp @@ -144,6 +144,11 @@ bool RealTimeTextChatRoom::canHandleParticipants () const { return false; } +shared_ptr RealTimeTextChatRoom::findParticipant (const Address &addr) const { + lError() << "findParticipant() is not allowed on a RealTimeTextChatRoom"; + return nullptr; +} + const Address *RealTimeTextChatRoom::getConferenceAddress () const { lError() << "a RealTimeTextChatRoom does not have a conference address"; return nullptr; @@ -181,6 +186,10 @@ void RealTimeTextChatRoom::removeParticipants (const list &participant, bool isAdmin) { + lError() << "setParticipantAdminStatus() is not allowed on a RealTimeTextChatRoom"; +} + void RealTimeTextChatRoom::setSubject (const string &subject) { L_D(); d->subject = subject; diff --git a/src/chat/real-time-text-chat-room.h b/src/chat/real-time-text-chat-room.h index ec7bdf929..ad2f12d37 100644 --- a/src/chat/real-time-text-chat-room.h +++ b/src/chat/real-time-text-chat-room.h @@ -47,6 +47,7 @@ public: void addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) override; void addParticipants (const std::list
&addresses, const CallSessionParams *params, bool hasMedia) override; bool canHandleParticipants () const override; + std::shared_ptr findParticipant (const Address &addr) const override; const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; @@ -55,6 +56,7 @@ public: void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) override; void setSubject (const std::string &subject) override; private: diff --git a/src/conference/conference-interface.h b/src/conference/conference-interface.h index a1d187991..443181f26 100644 --- a/src/conference/conference-interface.h +++ b/src/conference/conference-interface.h @@ -38,6 +38,7 @@ public: virtual void addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) = 0; virtual void addParticipants (const std::list
&addresses, const CallSessionParams *params, bool hasMedia) = 0; virtual bool canHandleParticipants () const = 0; + virtual std::shared_ptr findParticipant (const Address &addr) const = 0; virtual const Address *getConferenceAddress () const = 0; virtual int getNbParticipants () const = 0; virtual std::list> getParticipants () const = 0; @@ -46,6 +47,7 @@ public: virtual void leave () = 0; virtual void removeParticipant (const std::shared_ptr &participant) = 0; virtual void removeParticipants (const std::list> &participants) = 0; + virtual void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) = 0; virtual void setSubject (const std::string &subject) = 0; }; diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp index 1ed57424e..3ba9cf826 100644 --- a/src/conference/conference.cpp +++ b/src/conference/conference.cpp @@ -90,6 +90,10 @@ void Conference::removeParticipants (const list> &partic removeParticipant(p); } +void Conference::setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) { + lError() << "Conference class does not handle setParticipantAdminStatus() generically"; +} + void Conference::setSubject (const string &subject) { this->subject = subject; } diff --git a/src/conference/conference.h b/src/conference/conference.h index 57a4cdb44..cee450b11 100644 --- a/src/conference/conference.h +++ b/src/conference/conference.h @@ -46,7 +46,6 @@ public: LinphoneCore * getCore () const { return core; } - std::shared_ptr findParticipant (const Address &addr) const; std::shared_ptr findParticipant (const std::shared_ptr &session) const; public: @@ -54,6 +53,7 @@ public: void addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) override; void addParticipants (const std::list
&addresses, const CallSessionParams *params, bool hasMedia) override; bool canHandleParticipants () const override; + std::shared_ptr findParticipant (const Address &addr) const override; const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; @@ -62,6 +62,7 @@ public: void leave () override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) override; void setSubject (const std::string &subject) override; private: diff --git a/src/conference/participant-p.h b/src/conference/participant-p.h index f862c54a4..fabce499c 100644 --- a/src/conference/participant-p.h +++ b/src/conference/participant-p.h @@ -45,6 +45,7 @@ public: void subscribeToConferenceEventPackage (bool value) { _isSubscribedToConferenceEventPackage = value; } void removeSession () { session = nullptr; } void setAddress (const Address &newAddr) { addr = newAddr; } + void setAdmin (bool isAdmin) { this->isAdmin = isAdmin; } private: Address addr; diff --git a/src/conference/participant.cpp b/src/conference/participant.cpp index 6cfe04a0f..0c9fc5003 100644 --- a/src/conference/participant.cpp +++ b/src/conference/participant.cpp @@ -67,11 +67,6 @@ bool Participant::isAdmin () const { return d->isAdmin; } -void Participant::setAdmin (bool isAdmin) { - L_D(); - d->isAdmin = isAdmin; -} - // ============================================================================= ostream & operator<< (ostream &strm, const shared_ptr &participant) { diff --git a/src/conference/participant.h b/src/conference/participant.h index dea93ed98..707227425 100644 --- a/src/conference/participant.h +++ b/src/conference/participant.h @@ -49,9 +49,7 @@ public: explicit Participant (Address &&address); const Address& getAddress () const; - bool isAdmin () const; - void setAdmin (bool isAdmin); private: L_DECLARE_PRIVATE(Participant); diff --git a/tester/conference-event-tester.cpp b/tester/conference-event-tester.cpp index b578aa018..96db4c8cb 100644 --- a/tester/conference-event-tester.cpp +++ b/tester/conference-event-tester.cpp @@ -25,7 +25,7 @@ #include "conference/conference-listener.h" #include "conference/local-conference.h" #include "conference/local-conference-event-handler-p.h" -#include "conference/participant.h" +#include "conference/participant-p.h" #include "conference/remote-conference-event-handler-p.h" #include "tools/private-access.h" #include "tools/tester.h" @@ -766,7 +766,7 @@ void send_first_notify() { localConf.addParticipant(aliceAddr, ¶ms, false); localConf.setSubject("A random test subject"); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState(); @@ -814,7 +814,7 @@ void send_added_notify() { localConf.addParticipant(bobAddr, ¶ms, false); localConf.addParticipant(aliceAddr, ¶ms, false); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState(); @@ -867,7 +867,7 @@ void send_removed_notify() { localConf.addParticipant(bobAddr, ¶ms, false); localConf.addParticipant(aliceAddr, ¶ms, false); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState(); @@ -917,7 +917,7 @@ void send_admined_notify() { localConf.addParticipant(bobAddr, ¶ms, false); localConf.addParticipant(aliceAddr, ¶ms, false); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState(); @@ -967,7 +967,7 @@ void send_unadmined_notify() { localConf.addParticipant(bobAddr, ¶ms, false); localConf.addParticipant(aliceAddr, ¶ms, false); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState(); @@ -1019,7 +1019,7 @@ void send_subject_changed_notify () { localConf.addParticipant(aliceAddr, ¶ms, false); localConf.setSubject("A random test subject"); shared_ptr alice = localConf.findParticipant(aliceAddr); - alice->setAdmin(true); + L_GET_PRIVATE(alice)->setAdmin(true); LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE(localConf.getEventHandler()); L_ATTR_GET(static_cast(localConf), conferenceAddress) = addr; string notify = localHandlerPrivate->createNotifyFullState();