From 64e550f7643b456ec4c8d7de69d0711ad8f08b09 Mon Sep 17 00:00:00 2001 From: Erwan Croze Date: Fri, 27 Oct 2017 13:44:42 +0200 Subject: [PATCH] Merge fix for client group chat room --- coreapi/callbacks.c | 59 ++++++- coreapi/chat.c | 60 ++++++- coreapi/linphonecore.c | 97 ++++++++++- coreapi/private.h | 6 + include/linphone/core.h | 15 ++ src/CMakeLists.txt | 3 + src/address/address.h | 2 + src/c-wrapper/api/c-chat-room.cpp | 10 ++ src/c-wrapper/c-wrapper.h | 3 +- src/chat/chat-message/chat-message.h | 1 + src/chat/chat-room/client-group-chat-room.cpp | 3 +- src/chat/chat-room/server-group-chat-room-p.h | 66 ++++++++ .../chat-room/server-group-chat-room-stub.cpp | 157 ++++++++++++++++++ src/chat/chat-room/server-group-chat-room.h | 72 ++++++++ src/conference/local-conference.h | 2 + src/conference/participant.h | 2 + .../remote-conference-event-handler.cpp | 8 +- src/conference/session/call-session.h | 2 + src/sal/op.cpp | 2 +- 19 files changed, 552 insertions(+), 18 deletions(-) create mode 100644 src/chat/chat-room/server-group-chat-room-p.h create mode 100644 src/chat/chat-room/server-group-chat-room-stub.cpp create mode 100644 src/chat/chat-room/server-group-chat-room.h diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index ba4cea411..866ace059 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -40,6 +40,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/chat-room.h" +#include "chat/chat-room/server-group-chat-room-p.h" #include "conference/participant.h" #include "conference/session/call-session-p.h" #include "conference/session/call-session.h" @@ -115,6 +116,28 @@ static void call_received(SalCallOp *h) { fromAddr = linphone_address_new(h->get_from()); 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); + return; + } else if (sal_address_has_param(h->get_remote_contact_address(), "text")) { + linphone_address_unref(toAddr); + linphone_address_unref(fromAddr); + LinphonePrivate::Address addr(h->get_to()); + if (addr.isValid()) { + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, addr.asStringUriOnly().c_str()); + if (cr) { + L_GET_PRIVATE_FROM_C_OBJECT(cr, ServerGroupChatRoom)->confirmJoining(h); + return; + } + } + } else { + // TODO: handle media conference joining if the "text" feature tag is not present + } + /* First check if we can answer successfully to this invite */ LinphonePresenceActivity *activity = nullptr; if ((linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) @@ -720,18 +743,38 @@ static void on_notify_response(SalOp *op){ static void refer_received(SalOp *op, const SalAddress *refer_to){ if (sal_address_has_param(refer_to, "text")) { - LinphonePrivate::Address addr(sal_address_as_string(refer_to)); + char *refer_uri = sal_address_as_string(refer_to); + LinphonePrivate::Address addr(refer_uri); + bctbx_free(refer_uri); if (addr.isValid()) { LinphoneCore *lc = reinterpret_cast(op->get_sal()->get_user_pointer()); if (addr.hasUriParam("method") && (addr.getUriParamValue("method") == "BYE")) { - // The server asks a participant to leave a chat room - LinphoneChatRoom *cr = L_GET_C_BACK_PTR(lc->cppCore->findChatRoom(addr)); - if (cr) { - L_GET_CPP_PTR_FROM_C_OBJECT(cr)->leave(); - static_cast(op)->reply(SalReasonNone); - return; + if (linphone_core_conference_server_enabled(lc)) { + // Removal of a participant at the server side + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, op->get_to()); + if (cr) { + Address fromAddr(op->get_from()); + std::shared_ptr participant = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findParticipant(fromAddr); + if (!participant || !participant->isAdmin()) { + static_cast(op)->reply(SalReasonDeclined); + return; + } + participant = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findParticipant(addr); + if (participant) + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->removeParticipant(participant); + static_cast(op)->reply(SalReasonNone); + return; + } + } else { + // The server asks a participant to leave a chat room + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, addr.asStringUriOnly().c_str()); + if (cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->leave(); + static_cast(op)->reply(SalReasonNone); + return; + } + static_cast(op)->reply(SalReasonDeclined); } - static_cast(op)->reply(SalReasonDeclined); } else if (addr.hasParam("admin")) { LinphoneChatRoom *cr = L_GET_C_BACK_PTR(lc->cppCore->findChatRoom(Address(op->get_to()))); if (cr) { diff --git a/coreapi/chat.c b/coreapi/chat.c index 75a4e9636..87f07bc2e 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -79,8 +79,61 @@ LinphoneChatRoom *linphone_core_create_client_group_chat_room (LinphoneCore *lc, return L_GET_C_BACK_PTR(lc->cppCore->createClientGroupChatRoom(L_C_TO_STRING(subject))); } -void linphone_core_delete_chat_room (LinphoneCore *, LinphoneChatRoom *cr) { - LinphonePrivate::Core::deleteChatRoom(L_GET_CPP_PTR_FROM_C_OBJECT(cr)); +static LinphoneChatRoom *_linphone_core_get_or_create_chat_room(LinphoneCore *lc, const char *to) { + LinphoneAddress *to_addr = linphone_core_interpret_url(lc, to); + LinphoneChatRoom *ret; + + if (to_addr == NULL) { + ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s", to); + return NULL; + } + ret = _linphone_core_get_chat_room(lc, to_addr); + linphone_address_unref(to_addr); + if (!ret) { + ret = _linphone_core_create_chat_room_from_url(lc, to); + } + return ret; +} + +LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr) { + LinphoneChatRoom *ret = _linphone_core_get_chat_room(lc, addr); + if (!ret) { + ret = _linphone_core_create_chat_room(lc, addr); + } + return ret; +} + +LinphoneChatRoom * linphone_core_create_client_group_chat_room(LinphoneCore *lc, const char *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; +} + +LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc, LinphonePrivate::SalCallOp *op) { + LinphoneChatRoom *cr = _linphone_server_group_chat_room_new(lc, op); + _linphone_core_add_group_chat_room(lc, L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getConferenceAddress(), cr); + lc->chatrooms = bctbx_list_append(lc->chatrooms, cr); + return cr; +} + +void linphone_core_delete_chat_room(LinphoneCore *lc, LinphoneChatRoom *cr) { + if (bctbx_list_find(lc->chatrooms, cr)) { + lc->chatrooms = bctbx_list_remove(lc->chatrooms, cr); + linphone_chat_room_delete_history(cr); + linphone_chat_room_unref(cr); + } else { + ms_error("linphone_core_delete_chat_room(): chatroom [%p] isn't part of LinphoneCore.", cr); + } } LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) { @@ -89,7 +142,8 @@ LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const c int linphone_core_message_received(LinphoneCore *lc, LinphonePrivate::SalOp *op, const SalMessage *sal_msg) { LinphoneReason reason = LinphoneReasonNotAcceptable; - LinphoneChatRoom *cr = L_GET_C_BACK_PTR(lc->cppCore->findChatRoom(LinphonePrivate::Address(op->get_from()))); + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, + linphone_core_conference_server_enabled(lc) ? op->get_to() : op->get_from()); if (cr) reason = L_GET_PRIVATE_FROM_C_OBJECT(cr)->messageReceived(op, sal_msg); else { diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 156df2ba2..1a8145e96 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "quality_reporting.h" #include "lime.h" #include "conference_private.h" +#include "logger/logger.h" #ifdef SQLITE_STORAGE_ENABLED #include "sqlite3_bctbx_vfs.h" @@ -48,6 +49,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msvolume.h" #include "chat/chat-room/client-group-chat-room-p.h" +#include "chat/chat-room/server-group-chat-room-p.h" #include "conference/remote-conference-event-handler.h" #include "core/core.h" @@ -2137,11 +2139,25 @@ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEve } } +static void _linphone_core_conference_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + if ((linphone_event_get_subscription_dir(lev) == LinphoneSubscriptionIncoming) && (state == LinphoneSubscriptionIncomingReceived)) { + const LinphoneAddress *resource = linphone_event_get_resource(lev); + char *resourceUri = linphone_address_as_string_uri_only(resource); + LinphoneChatRoom *cr = _linphone_core_find_group_chat_room(lc, resourceUri); + bctbx_free(resourceUri); + if (cr) { + linphone_event_accept_subscription(lev); + L_GET_PRIVATE_FROM_C_OBJECT(cr, ServerGroupChatRoom)->subscribeReceived(lev); + } else + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); + } +} + static void linphone_core_internal_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { if (strcasecmp(linphone_event_get_name(lev), "Presence") == 0) { linphone_friend_list_subscription_state_changed(lc, lev, state); } else if (strcmp(linphone_event_get_name(lev), "conference") == 0) { - + _linphone_core_conference_subscription_state_changed(lc, lev, state); } } @@ -7146,7 +7162,84 @@ void linphone_core_set_conference_factory_uri(LinphoneCore *lc, const char *uri) } const char * linphone_core_get_conference_factory_uri(const LinphoneCore *lc) { - return lp_config_get_string(linphone_core_get_config(lc), "misc", "conference_factory_uri", nullptr); + return lp_config_get_string(linphone_core_get_config(lc), "misc", "conference_factory_uri", "sip:"); +} + +bool_t _linphone_core_has_group_chat_room(const LinphoneCore *lc, const char *id) { + bool_t result; + bctbx_iterator_t *it = bctbx_map_cchar_find_key(lc->group_chat_rooms, id); + bctbx_iterator_t *endit = bctbx_map_cchar_end(lc->group_chat_rooms); + result = !bctbx_iterator_cchar_equals(it, endit); + bctbx_iterator_cchar_delete(endit); + bctbx_iterator_cchar_delete(it); + return result; +} + +void _linphone_core_add_group_chat_room(LinphoneCore *lc, const LinphonePrivate::Address &addr, LinphoneChatRoom *cr) { + Address cleanedAddr(addr); + cleanedAddr.clean(); + cleanedAddr.setPort(0); + bctbx_pair_t *pair = reinterpret_cast(bctbx_pair_cchar_new(cleanedAddr.asStringUriOnly().c_str(), linphone_chat_room_ref(cr))); + bctbx_map_cchar_insert_and_delete(lc->group_chat_rooms, pair); +} + +void _linphone_core_remove_group_chat_room(LinphoneCore *lc, LinphoneChatRoom *cr) { + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(cr); + Address cleanedAddr(*L_GET_CPP_PTR_FROM_C_OBJECT(confAddr)); + cleanedAddr.clean(); + cleanedAddr.setPort(0); + bctbx_iterator_t *it = bctbx_map_cchar_find_key(lc->group_chat_rooms, cleanedAddr.asStringUriOnly().c_str()); + bctbx_iterator_t *endit = bctbx_map_cchar_end(lc->group_chat_rooms); + if (!bctbx_iterator_cchar_equals(it, endit)) { + bctbx_map_cchar_erase(lc->group_chat_rooms, it); + linphone_chat_room_unref(cr); + } + bctbx_iterator_cchar_delete(endit); + bctbx_iterator_cchar_delete(it); +} + +LinphoneChatRoom *_linphone_core_find_group_chat_room(const LinphoneCore *lc, const char *id) { + LinphoneChatRoom *result = nullptr; + Address cleanedAddr(id); + cleanedAddr.clean(); + cleanedAddr.setPort(0); + bctbx_iterator_t *it = bctbx_map_cchar_find_key(lc->group_chat_rooms, cleanedAddr.asStringUriOnly().c_str()); + bctbx_iterator_t *endit = bctbx_map_cchar_end(lc->group_chat_rooms); + if (!bctbx_iterator_cchar_equals(it, endit)) { + result = reinterpret_cast(bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); + } else { + bctbx_iterator_cchar_delete(it); + Address backupAddress(cleanedAddr); + Address factoryAddress(linphone_core_get_conference_factory_uri(lc)); + backupAddress.setDomain(factoryAddress.getDomain()); + lWarning() << "We don't found the chat room with address " << id << " as a temporary workaround, searching with " << backupAddress.asString(); + it = bctbx_map_cchar_find_key(lc->group_chat_rooms, backupAddress.asStringUriOnly().c_str()); + + if (!bctbx_iterator_cchar_equals(it, endit)) { + result = reinterpret_cast(bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); + } + if (!result) lWarning() << "Chatroom " << id << " or " << backupAddress.asString() << " not found!"; + } + bctbx_iterator_cchar_delete(endit); + bctbx_iterator_cchar_delete(it); + return result; +} + +void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable) { + lp_config_set_int(linphone_core_get_config(lc), "misc", "conference_server_enabled", enable); +} + +bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc) { + return lp_config_get_int(linphone_core_get_config(lc), "misc", "conference_server_enabled", FALSE) ? TRUE : FALSE; +} + +bool_t _linphone_core_is_conference_creation (const LinphoneCore *lc, const LinphoneAddress *addr) { + LinphoneAddress *factoryAddr = linphone_address_new(linphone_core_get_conference_factory_uri(lc)); + if (!factoryAddr) + return FALSE; + bool_t result = linphone_address_weak_equal(factoryAddr, addr); + linphone_address_unref(factoryAddr); + return result; } void linphone_core_set_tls_cert(LinphoneCore *lc, const char *tls_cert) { diff --git a/coreapi/private.h b/coreapi/private.h index be2eec3f1..7186c546d 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -457,6 +457,11 @@ bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription extern LinphonePrivate::Sal::Callbacks linphone_sal_callbacks; LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); LINPHONE_PUBLIC bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc); +bool_t _linphone_core_has_group_chat_room (const LinphoneCore *lc, const char *id); +void _linphone_core_add_group_chat_room (LinphoneCore *lc, const LinphonePrivate::Address &addr, LinphoneChatRoom *cr); +void _linphone_core_remove_group_chat_room(LinphoneCore *lc, LinphoneChatRoom *cr); +bool_t _linphone_core_is_conference_creation (const LinphoneCore *lc, const LinphoneAddress *addr); +LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc, LinphonePrivate::SalCallOp *op); void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description); @@ -472,6 +477,7 @@ 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 *uri, const char *subject); +LinphoneChatRoom *_linphone_server_group_chat_room_new (LinphoneCore *core, LinphonePrivate::SalCallOp *op); 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/include/linphone/core.h b/include/linphone/core.h index 336d1d7c4..0ecc1ae5d 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -4235,6 +4235,21 @@ void linphone_core_set_conference_factory_uri(LinphoneCore *lc, const char *uri) */ const char * linphone_core_get_conference_factory_uri(const LinphoneCore *lc); +/** + * Enable the conference server feature. This has the effect to listen of the conference factory uri + * to create new conferences when receiving INVITE messages there. + * @param[in] lc A #LinphoneCore object + * @param[in] enable A boolean value telling whether to enable or disable the conference server feature + */ +void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable); + +/** + * Tells whether the conference server feature is enabled. + * @param[in] lc A #LinphoneCore object + * @return A boolean value telling whether the conference server feature is enabled or not + */ +bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc); + /** * @} */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 37de6f4dd..98304a28c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,8 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES chat/chat-room/client-group-chat-room.h chat/chat-room/real-time-text-chat-room-p.h chat/chat-room/real-time-text-chat-room.h + chat/chat-room/server-group-chat-room-p.h + chat/chat-room/server-group-chat-room.h chat/cpim/cpim.h chat/cpim/header/cpim-core-headers.h chat/cpim/header/cpim-generic-header.h @@ -150,6 +152,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES chat/chat-room/chat-room.cpp chat/chat-room/client-group-chat-room.cpp chat/chat-room/real-time-text-chat-room.cpp + chat/chat-room/server-group-chat-room-stub.cpp chat/cpim/header/cpim-core-headers.cpp chat/cpim/header/cpim-generic-header.cpp chat/cpim/header/cpim-header.cpp diff --git a/src/address/address.h b/src/address/address.h index b765067d3..af3dc0f1f 100644 --- a/src/address/address.h +++ b/src/address/address.h @@ -34,6 +34,8 @@ class LINPHONE_PUBLIC Address : public ClonableObject { friend class CallSession; friend class ClientGroupChatRoom; friend class ClientGroupChatRoomPrivate; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; public: explicit Address (const std::string &address = ""); diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index c86f16391..c30abf7dc 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -28,8 +28,10 @@ #include "chat/chat-room/basic-chat-room.h" #include "chat/chat-room/client-group-chat-room.h" #include "chat/chat-room/real-time-text-chat-room-p.h" +#include "chat/chat-room/server-group-chat-room-p.h" #include "conference/participant.h" #include "core/core-p.h" +#include "content/content.h" // ============================================================================= @@ -352,6 +354,14 @@ LinphoneChatRoom *_linphone_client_group_chat_room_new (LinphoneCore *core, cons return cr; } +LinphoneChatRoom *_linphone_server_group_chat_room_new (LinphoneCore *core, LinphonePrivate::SalCallOp *op) { + LinphoneChatRoom *cr = L_INIT(ChatRoom); + L_SET_CPP_PTR_FROM_C_OBJECT(cr, LinphonePrivate::ObjectFactory::create(core, op)); + L_GET_PRIVATE_FROM_C_OBJECT(cr)->setState(LinphonePrivate::ChatRoom::State::Instantiated); + L_GET_PRIVATE_FROM_C_OBJECT(cr, ServerGroupChatRoom)->confirmCreation(); + return cr; +} + /* DEPRECATED */ void linphone_chat_room_destroy (LinphoneChatRoom *cr) { linphone_chat_room_unref(cr); diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index 851385f5b..885a1c809 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -51,7 +51,8 @@ F(EventLog, ConferenceNotifiedEvent) \ F(EventLog, ConferenceParticipantDeviceEvent) \ F(EventLog, ConferenceParticipantEvent) \ - F(EventLog, ConferenceSubjectEvent) + F(EventLog, ConferenceSubjectEvent) \ + F(ChatRoom, ServerGroupChatRoom) // ============================================================================= // Register belle-sip ID. diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index b1c0a0139..76ae99890 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -41,6 +41,7 @@ class LINPHONE_PUBLIC ChatMessage : public Object { friend class ChatRoomPrivate; friend class CpimChatMessageModifier; friend class RealTimeTextChatRoomPrivate; + friend class ServerGroupChatRoomPrivate; public: L_OVERRIDE_SHARED_FROM_THIS(ChatMessage); diff --git a/src/chat/chat-room/client-group-chat-room.cpp b/src/chat/chat-room/client-group-chat-room.cpp index 73ac9d595..1e89cf723 100644 --- a/src/chat/chat-room/client-group-chat-room.cpp +++ b/src/chat/chat-room/client-group-chat-room.cpp @@ -441,8 +441,7 @@ void ClientGroupChatRoom::onCallSessionStateChanged ( if (state == LinphoneCallConnected) { if (d->state == ChatRoom::State::CreationPending) { - Address addr(session->getRemoteContact()); - addr.clean(); + Address addr(session->getRemoteContactAddress()->asStringUriOnly()); onConferenceCreated(addr); if (session->getRemoteContactAddress()->hasParam("isfocus")) dConference->eventHandler->subscribe(getConferenceAddress()); diff --git a/src/chat/chat-room/server-group-chat-room-p.h b/src/chat/chat-room/server-group-chat-room-p.h new file mode 100644 index 000000000..5df197179 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room-p.h @@ -0,0 +1,66 @@ +/* + * server-group-chat-room-p.h + * Copyright (C) 2010-2017 Belledonne Communications SARL + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _SERVER_GROUP_CHAT_ROOM_P_H_ +#define _SERVER_GROUP_CHAT_ROOM_P_H_ + +// From coreapi. +#include "private.h" + +#include "address/address.h" +#include "chat-room-p.h" +#include "server-group-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Participant; + +class ServerGroupChatRoomPrivate : public ChatRoomPrivate { +public: + ServerGroupChatRoomPrivate (LinphoneCore *core); + virtual ~ServerGroupChatRoomPrivate () = default; + + std::shared_ptr addParticipant (const Address &addr); + void confirmCreation (); + void confirmJoining (SalCallOp *op); + std::shared_ptr findRemovedParticipant (const std::shared_ptr &session) const; + std::string generateConferenceId () const; + void removeParticipant (const std::shared_ptr &participant); + void subscribeReceived (LinphoneEvent *event); + void update (SalCallOp *op); + + void dispatchMessage (const Address &fromAddr, const Content &content); + void storeOrUpdateMessage (const std::shared_ptr &msg) override; + LinphoneReason messageReceived (SalOp *op, const SalMessage *msg) override; + +private: + void designateAdmin (); + bool isAdminLeft () const; + +private: + L_DECLARE_PUBLIC(ServerGroupChatRoom); + + std::list> removedParticipants; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _SERVER_GROUP_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/server-group-chat-room-stub.cpp b/src/chat/chat-room/server-group-chat-room-stub.cpp new file mode 100644 index 000000000..da4ef27a3 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room-stub.cpp @@ -0,0 +1,157 @@ +/* + * server-group-chat-room.cpp + * Copyright (C) 2010-2017 Belledonne Communications SARL + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "address/address-p.h" +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/modifier/cpim-chat-message-modifier.h" +#include "conference/local-conference-event-handler.h" +#include "conference/local-conference-p.h" +#include "conference/participant-p.h" +#include "conference/session/call-session-p.h" +#include "content/content-type.h" +#include "logger/logger.h" +#include "sal/refer-op.h" +#include "server-group-chat-room-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +ServerGroupChatRoomPrivate::ServerGroupChatRoomPrivate (LinphoneCore *core) : ChatRoomPrivate(core) {} + +// ----------------------------------------------------------------------------- + +shared_ptr ServerGroupChatRoomPrivate::addParticipant (const Address &addr) { + return nullptr; +} + +void ServerGroupChatRoomPrivate::confirmCreation () { +} + +void ServerGroupChatRoomPrivate::confirmJoining (SalCallOp *op) { +} + +shared_ptr ServerGroupChatRoomPrivate::findRemovedParticipant (const shared_ptr &session) const { + return nullptr; +} + +string ServerGroupChatRoomPrivate::generateConferenceId () const { + return ""; +} + +void ServerGroupChatRoomPrivate::removeParticipant (const shared_ptr &participant) { +} + +void ServerGroupChatRoomPrivate::subscribeReceived (LinphoneEvent *event) { +} + +void ServerGroupChatRoomPrivate::update (SalCallOp *op) { +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::dispatchMessage (const Address &fromAddr, const Content &content) { +} + +void ServerGroupChatRoomPrivate::storeOrUpdateMessage (const std::shared_ptr &msg) { +} + +LinphoneReason ServerGroupChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *salMsg) { + return LinphoneReasonNone; +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::designateAdmin () { +} + +bool ServerGroupChatRoomPrivate::isAdminLeft () const { + return false; +} + +// ============================================================================= + +ServerGroupChatRoom::ServerGroupChatRoom (LinphoneCore *core, SalCallOp *op) + : ChatRoom(*new ServerGroupChatRoomPrivate(core)), LocalConference(core, Address(op->get_to()), nullptr) { +} + +int ServerGroupChatRoom::getCapabilities () const { + return 0; +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoom::addParticipant (const Address &addr, const CallSessionParams *params, bool hasMedia) { +} + +void ServerGroupChatRoom::addParticipants (const list
&addresses, const CallSessionParams *params, bool hasMedia) { +} + +bool ServerGroupChatRoom::canHandleParticipants () const { + return FALSE; +} + +shared_ptr ServerGroupChatRoom::findParticipant (const Address &addr) const { + return nullptr; +} + +const Address &ServerGroupChatRoom::getConferenceAddress () const { + return LocalConference::getConferenceAddress(); +} + +int ServerGroupChatRoom::getNbParticipants () const { + return 0; +} + +list> ServerGroupChatRoom::getParticipants () const { + return LocalConference::getParticipants(); +} + +const string &ServerGroupChatRoom::getSubject () const { + return LocalConference::getSubject(); +} + +void ServerGroupChatRoom::join () {} + +void ServerGroupChatRoom::leave () {} + +void ServerGroupChatRoom::removeParticipant (const shared_ptr &participant) { +} + +void ServerGroupChatRoom::removeParticipants (const list> &participants) { +} + +void ServerGroupChatRoom::setParticipantAdminStatus (shared_ptr &participant, bool isAdmin) { +} + +void ServerGroupChatRoom::setSubject (const std::string &subject) { +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoom::onCallSessionStateChanged (const std::shared_ptr &session, LinphoneCallState state, const std::string &message) { +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/server-group-chat-room.h b/src/chat/chat-room/server-group-chat-room.h new file mode 100644 index 000000000..efe5f79f0 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room.h @@ -0,0 +1,72 @@ +/* + * server-group-chat-room.h + * Copyright (C) 2010-2017 Belledonne Communications SARL + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _SERVER_GROUP_CHAT_ROOM_H_ +#define _SERVER_GROUP_CHAT_ROOM_H_ + +// From coreapi +#include "private.h" + +#include "chat/chat-room/chat-room.h" +#include "conference/local-conference.h" + +#include "linphone/types.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ServerGroupChatRoomPrivate; + +class ServerGroupChatRoom : public ChatRoom, public LocalConference { +public: + ServerGroupChatRoom (LinphoneCore *core, SalCallOp *op); + virtual ~ServerGroupChatRoom () = default; + + int getCapabilities () const override; + +public: + /* ConferenceInterface */ + 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; + 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; + void setParticipantAdminStatus (std::shared_ptr &participant, bool isAdmin) override; + void setSubject (const std::string &subject) override; + +private: + /* CallSessionListener */ + void onCallSessionStateChanged (const std::shared_ptr &session, LinphoneCallState state, const std::string &message) override; + +private: + L_DECLARE_PRIVATE(ServerGroupChatRoom); + L_DISABLE_COPY(ServerGroupChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _SERVER_GROUP_CHAT_ROOM_H_ diff --git a/src/conference/local-conference.h b/src/conference/local-conference.h index 0c425447a..f27b8f75b 100644 --- a/src/conference/local-conference.h +++ b/src/conference/local-conference.h @@ -29,6 +29,8 @@ LINPHONE_BEGIN_NAMESPACE class LocalConferencePrivate; class LocalConference : public Conference { + friend class ServerGroupChatRoomPrivate; + public: LocalConference (LinphoneCore *core, const Address &myAddress, CallListener *listener = nullptr); diff --git a/src/conference/participant.h b/src/conference/participant.h index a1b2904c3..aefe33fab 100644 --- a/src/conference/participant.h +++ b/src/conference/participant.h @@ -45,6 +45,8 @@ class Participant : public Object { friend class LocalConferenceEventHandlerPrivate; friend class MediaSessionPrivate; friend class RemoteConference; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; public: explicit Participant (const Address &address); diff --git a/src/conference/remote-conference-event-handler.cpp b/src/conference/remote-conference-event-handler.cpp index 41430353e..da3f19de8 100644 --- a/src/conference/remote-conference-event-handler.cpp +++ b/src/conference/remote-conference-event-handler.cpp @@ -78,8 +78,14 @@ void RemoteConferenceEventHandler::notifyReceived (const string &xmlBody) { tm = static_cast(Utils::stoll(confInfo->getConferenceDescription()->getFreeText().get())); Address cleanedConfAddress = d->confAddress; + cleanedConfAddress.clean(); cleanedConfAddress.setPort(0); - if (confInfo->getEntity() == cleanedConfAddress.asString()) { + // Temporary workaround + Address entityAddress(confInfo->getEntity().c_str()); + Address cleanedConfAddress2(cleanedConfAddress); + cleanedConfAddress2.setDomain(entityAddress.getDomain()); + if (confInfo->getEntity() == cleanedConfAddress.asString() + || confInfo->getEntity() == cleanedConfAddress2.asString()) { if (confInfo->getConferenceDescription().present() && confInfo->getConferenceDescription().get().getSubject().present()) d->listener->onSubjectChanged(tm, confInfo->getConferenceDescription().get().getSubject().get()); diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index c0eaccc8b..70470d443 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -40,6 +40,8 @@ class LINPHONE_PUBLIC CallSession : public Object { friend class ClientGroupChatRoom; friend class ClientGroupChatRoomPrivate; friend class Conference; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; public: L_OVERRIDE_SHARED_FROM_THIS(CallSession); diff --git a/src/sal/op.cpp b/src/sal/op.cpp index e9a07b34a..896aafd45 100644 --- a/src/sal/op.cpp +++ b/src/sal/op.cpp @@ -426,7 +426,7 @@ int SalOp::process_redirect(){ belle_sip_request_set_uri(request, redirect_uri); redirect_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(redirect_uri))); belle_sip_uri_set_port(redirect_uri, 0); - belle_sip_uri_set_transport_param(redirect_uri, nullptr); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(redirect_uri), "transport"); belle_sip_header_address_set_uri((belle_sip_header_address_t*)to, redirect_uri); send_request(request); return 0;