diff --git a/coreapi/sal/sal.cpp b/coreapi/sal/sal.cpp index fb5d91dd0..520c2d6d8 100644 --- a/coreapi/sal/sal.cpp +++ b/coreapi/sal/sal.cpp @@ -52,6 +52,7 @@ void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *ev belle_sip_header_t *evh; const char *method=belle_sip_request_get_method(req); belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); + belle_sip_header_t *subjectHeader = belle_sip_message_get_header(BELLE_SIP_MESSAGE(req), "Subject"); from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); @@ -161,6 +162,11 @@ void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *ev belle_sip_object_unref(address); } + if (subjectHeader) { + const char *subject = belle_sip_header_get_unparsed_value(subjectHeader); + op->set_subject(subject); + } + if(!op->diversion_address){ diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t); if (diversion) { diff --git a/coreapi/sal/sal_op.cpp b/coreapi/sal/sal_op.cpp index a72cae041..a73d018ce 100644 --- a/coreapi/sal/sal_op.cpp +++ b/coreapi/sal/sal_op.cpp @@ -65,6 +65,10 @@ SalOp::~SalOp() { ms_free(this->to); this->to=NULL; } + if (this->subject) { + ms_free(this->subject); + this->subject = NULL; + } if (this->route) { ms_free(this->route); this->route=NULL; @@ -198,6 +202,10 @@ void SalOp::set_realm(const char *realm) { assign_string(&this->name,name##_string); \ if(name##_string) ms_free(name##_string); +void SalOp::set_subject (const char *subject) { + assign_string(&this->subject, subject); +} + void SalOp::set_from(const char *from){ SET_PARAM(from); } diff --git a/coreapi/sal/sal_op.h b/coreapi/sal/sal_op.h index d30b3b4d8..118784620 100644 --- a/coreapi/sal/sal_op.h +++ b/coreapi/sal/sal_op.h @@ -41,8 +41,11 @@ public: void set_user_pointer(void *up) {this->user_pointer=up;} void *get_user_pointer() const {return this->user_pointer;} - - + + + void set_subject (const char *subject); + const char *get_subject () const { return this->subject; } + void set_from(const char *from); void set_from_address(const SalAddress *from); const char *get_from() const {return this->from;} @@ -197,6 +200,7 @@ protected: char *route = NULL; /*or request-uri for REGISTER*/ MSList* route_addresses = NULL; /*list of SalAddress* */ SalAddress* contact_address = NULL; + char *subject = NULL; char *from = NULL; SalAddress* from_address = NULL; char *to = NULL; diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index 0b82cdb43..d98c05de9 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -282,6 +282,13 @@ LINPHONE_PUBLIC int linphone_chat_room_get_nb_participants (const LinphoneChatRo */ LINPHONE_PUBLIC bctbx_list_t * linphone_chat_room_get_participants (const LinphoneChatRoom *cr); +/** + * Get the subject of a chat room. + * @param[in] cr A LinphoneChatRoom object + * @return The subject of the chat room + */ +LINPHONE_PUBLIC const char * linphone_chat_room_get_subject (const LinphoneChatRoom *cr); + /** * Remove a participant of a chat room. * @param[in] cr A LinphoneChatRoom object @@ -296,6 +303,13 @@ 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); +/** + * Set the subject of a chat room. + * @param[in] cr A LinphoneChatRoom object + * @param[in] subject The new subject to set for the chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_set_subject (LinphoneChatRoom *cr, const char *subject); + /** * Returns back pointer to #LinphoneCore object. * @deprecated use linphone_chat_room_get_core() diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index 1b78fd9e8..3bc39f348 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -245,6 +245,10 @@ bctbx_list_t *linphone_chat_room_get_participants (const LinphoneChatRoom *cr) { return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getParticipants()); } +const char * linphone_chat_room_get_subject (const LinphoneChatRoom *cr) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getSubject()); +} + void linphone_chat_room_remove_participant (LinphoneChatRoom *cr, LinphoneParticipant *participant) { L_GET_CPP_PTR_FROM_C_OBJECT(cr)->removeParticipant(L_GET_CPP_PTR_FROM_C_OBJECT(participant)); } @@ -253,6 +257,10 @@ 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_subject (LinphoneChatRoom *cr, const char *subject) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setSubject(L_C_TO_STRING(subject)); +} + // ============================================================================= // Reference and user data handling functions. // ============================================================================= diff --git a/src/chat/basic-chat-room-p.h b/src/chat/basic-chat-room-p.h index 54d3d9fe5..056ba79f1 100644 --- a/src/chat/basic-chat-room-p.h +++ b/src/chat/basic-chat-room-p.h @@ -35,6 +35,8 @@ public: virtual ~BasicChatRoomPrivate () = default; private: + std::string subject; + L_DECLARE_PUBLIC(BasicChatRoom); }; diff --git a/src/chat/basic-chat-room.cpp b/src/chat/basic-chat-room.cpp index 820ffc6cd..2d41a5657 100644 --- a/src/chat/basic-chat-room.cpp +++ b/src/chat/basic-chat-room.cpp @@ -64,6 +64,11 @@ list> BasicChatRoom::getParticipants () const { return l; } +const string &BasicChatRoom::getSubject () const { + L_D(); + return d->subject; +} + void BasicChatRoom::removeParticipant (const shared_ptr &participant) { lError() << "removeParticipant() is not allowed on a BasicChatRoom"; } @@ -72,4 +77,9 @@ void BasicChatRoom::removeParticipants (const list> &par lError() << "removeParticipants() is not allowed on a BasicChatRoom"; } +void BasicChatRoom::setSubject (const string &subject) { + L_D(); + d->subject = subject; +} + LINPHONE_END_NAMESPACE diff --git a/src/chat/basic-chat-room.h b/src/chat/basic-chat-room.h index d7aae693a..b80a771de 100644 --- a/src/chat/basic-chat-room.h +++ b/src/chat/basic-chat-room.h @@ -39,8 +39,10 @@ public: const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; + const std::string &getSubject () const override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setSubject (const std::string &subject) override; private: L_DECLARE_PRIVATE(BasicChatRoom); diff --git a/src/chat/client-group-chat-room-p.h b/src/chat/client-group-chat-room-p.h index ef642bc6c..346faf869 100644 --- a/src/chat/client-group-chat-room-p.h +++ b/src/chat/client-group-chat-room-p.h @@ -31,12 +31,10 @@ LINPHONE_BEGIN_NAMESPACE class ClientGroupChatRoomPrivate : public ChatRoomPrivate { public: - ClientGroupChatRoomPrivate (LinphoneCore *core, const std::string &subject); + ClientGroupChatRoomPrivate (LinphoneCore *core); virtual ~ClientGroupChatRoomPrivate () = default; private: - std::string subject; - L_DECLARE_PUBLIC(ClientGroupChatRoom); }; diff --git a/src/chat/client-group-chat-room.cpp b/src/chat/client-group-chat-room.cpp index 57e65cdc1..fb21ca9cc 100644 --- a/src/chat/client-group-chat-room.cpp +++ b/src/chat/client-group-chat-room.cpp @@ -31,15 +31,16 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -ClientGroupChatRoomPrivate::ClientGroupChatRoomPrivate (LinphoneCore *core, const string &subject) - : ChatRoomPrivate(core), subject(subject) {} +ClientGroupChatRoomPrivate::ClientGroupChatRoomPrivate (LinphoneCore *core) + : ChatRoomPrivate(core) {} // ============================================================================= ClientGroupChatRoom::ClientGroupChatRoom (LinphoneCore *core, const Address &me, const string &subject) - : ChatRoom(*new ClientGroupChatRoomPrivate(core, subject)), RemoteConference(core, me, nullptr) { + : ChatRoom(*new ClientGroupChatRoomPrivate(core)), RemoteConference(core, me, nullptr) { string factoryUri = linphone_core_get_conference_factory_uri(core); focus = make_shared(factoryUri); + this->subject = subject; } // ----------------------------------------------------------------------------- @@ -73,7 +74,7 @@ void ClientGroupChatRoom::addParticipants (const list
&addresses, const Address addr = me->getAddress(); addr.setParam("text", ""); session->getPrivate()->getOp()->set_contact_address(addr.getPrivate()->getInternalAddress()); - session->startInvite(nullptr, d->subject); + session->startInvite(nullptr, subject); d->setState(ChatRoom::State::CreationPending); } // TODO @@ -95,6 +96,10 @@ list> ClientGroupChatRoom::getParticipants () const { return RemoteConference::getParticipants(); } +const string &ClientGroupChatRoom::getSubject () const { + return RemoteConference::getSubject(); +} + void ClientGroupChatRoom::removeParticipant (const shared_ptr &participant) { // TODO } @@ -103,6 +108,20 @@ void ClientGroupChatRoom::removeParticipants (const list // TODO } +void ClientGroupChatRoom::setSubject (const string &subject) { + L_D(); + if (d->state != ChatRoom::State::Created) { + lError() << "Cannot change the ClientGroupChatRoom subject in a state other than Created"; + return; + } + if (!me->isAdmin()) { + lError() << "Cannot change the ClientGroupChatRoom subject because I am not admin"; + return; + } + shared_ptr session = focus->getPrivate()->getSession(); + session->update(nullptr, subject); +} + // ----------------------------------------------------------------------------- void ClientGroupChatRoom::onConferenceCreated (const Address &addr) { diff --git a/src/chat/client-group-chat-room.h b/src/chat/client-group-chat-room.h index d5f1c5b1a..05ba772f7 100644 --- a/src/chat/client-group-chat-room.h +++ b/src/chat/client-group-chat-room.h @@ -47,8 +47,10 @@ public: const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; + const std::string &getSubject () const override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setSubject (const std::string &subject) override; private: /* ConferenceListener */ diff --git a/src/chat/real-time-text-chat-room-p.h b/src/chat/real-time-text-chat-room-p.h index 5aaf502c2..88e4e7df4 100644 --- a/src/chat/real-time-text-chat-room-p.h +++ b/src/chat/real-time-text-chat-room-p.h @@ -46,6 +46,8 @@ public: std::shared_ptr pendingMessage = nullptr; private: + std::string subject; + L_DECLARE_PUBLIC(RealTimeTextChatRoom); }; diff --git a/src/chat/real-time-text-chat-room.cpp b/src/chat/real-time-text-chat-room.cpp index 0a4939735..885b98e33 100644 --- a/src/chat/real-time-text-chat-room.cpp +++ b/src/chat/real-time-text-chat-room.cpp @@ -160,6 +160,11 @@ list> RealTimeTextChatRoom::getParticipants () const { return l; } +const string &RealTimeTextChatRoom::getSubject () const { + L_D(); + return d->subject; +} + void RealTimeTextChatRoom::removeParticipant (const shared_ptr &participant) { lError() << "removeParticipant() is not allowed on a RealTimeTextChatRoom"; } @@ -168,4 +173,9 @@ void RealTimeTextChatRoom::removeParticipants (const listsubject = subject; +} + LINPHONE_END_NAMESPACE diff --git a/src/chat/real-time-text-chat-room.h b/src/chat/real-time-text-chat-room.h index 524296521..f9a7c077c 100644 --- a/src/chat/real-time-text-chat-room.h +++ b/src/chat/real-time-text-chat-room.h @@ -49,8 +49,10 @@ public: const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; + const std::string &getSubject () const override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setSubject (const std::string &subject) override; private: L_DECLARE_PRIVATE(RealTimeTextChatRoom); diff --git a/src/conference/conference-interface.h b/src/conference/conference-interface.h index 1cd62ec6d..1058ff8e6 100644 --- a/src/conference/conference-interface.h +++ b/src/conference/conference-interface.h @@ -40,8 +40,10 @@ public: virtual const Address *getConferenceAddress () const = 0; virtual int getNbParticipants () const = 0; virtual std::list> getParticipants () const = 0; + virtual const std::string &getSubject () const = 0; virtual void removeParticipant (const std::shared_ptr &participant) = 0; virtual void removeParticipants (const std::list> &participants) = 0; + virtual void setSubject (const std::string &subject) = 0; }; LINPHONE_END_NAMESPACE diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp index 0bd79f1f8..818273165 100644 --- a/src/conference/conference.cpp +++ b/src/conference/conference.cpp @@ -66,6 +66,10 @@ list> Conference::getParticipants () const { return participants; } +const string &Conference::getSubject () const { + return subject; +} + void Conference::removeParticipant (const shared_ptr &participant) { lError() << "Conference class does not handle removeParticipant() generically"; } @@ -75,6 +79,10 @@ void Conference::removeParticipants (const list> &partic removeParticipant(p); } +void Conference::setSubject (const string &subject) { + this->subject = subject; +} + // ----------------------------------------------------------------------------- void Conference::onAckBeingSent (const CallSession &session, LinphoneHeaders *headers) { diff --git a/src/conference/conference.h b/src/conference/conference.h index b9a89cd31..e83debbbe 100644 --- a/src/conference/conference.h +++ b/src/conference/conference.h @@ -53,8 +53,10 @@ public: const Address *getConferenceAddress () const override; int getNbParticipants () const override; std::list> getParticipants () const override; + const std::string &getSubject () const override; void removeParticipant (const std::shared_ptr &participant) override; void removeParticipants (const std::list> &participants) override; + void setSubject (const std::string &subject) override; private: /* CallSessionListener */ @@ -87,6 +89,7 @@ protected: std::shared_ptr me; std::list> participants; Address conferenceAddress; + std::string subject; private: L_DISABLE_COPY(Conference); diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index c1b68870f..924aed37a 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -64,7 +64,7 @@ protected: virtual void setReleased (); virtual void setTerminated (); virtual LinphoneStatus startAcceptUpdate (LinphoneCallState nextState, const std::string &stateInfo); - virtual LinphoneStatus startUpdate (); + virtual LinphoneStatus startUpdate (const std::string &subject); virtual void terminate (); virtual void updateCurrentParams () const; @@ -85,6 +85,7 @@ protected: mutable CallSessionParams *currentParams = nullptr; CallSessionParams *remoteParams = nullptr; + std::string subject; LinphoneCallDir direction = LinphoneCallOutgoing; LinphoneCallState state = LinphoneCallIdle; LinphoneCallState prevState = LinphoneCallIdle; diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index eb1922516..3bb20e55e 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -564,23 +564,25 @@ LinphoneStatus CallSessionPrivate::startAcceptUpdate (LinphoneCallState nextStat return 0; } -LinphoneStatus CallSessionPrivate::startUpdate () { +LinphoneStatus CallSessionPrivate::startUpdate (const string &subject) { L_Q(); - string subject; - if (q->getParams()->getPrivate()->getInConference()) - subject = "Conference"; - else if (q->getParams()->getPrivate()->getInternalCallUpdate()) - subject = "ICE processing concluded"; - else if (q->getParams()->getPrivate()->getNoUserConsent()) - subject = "Refreshing"; - else - subject = "Media change"; + string newSubject(subject); + if (newSubject.empty()) { + if (q->getParams()->getPrivate()->getInConference()) + newSubject = "Conference"; + else if (q->getParams()->getPrivate()->getInternalCallUpdate()) + newSubject = "ICE processing concluded"; + else if (q->getParams()->getPrivate()->getNoUserConsent()) + newSubject = "Refreshing"; + else + newSubject = "Media change"; + } if (destProxy && destProxy->op) { /* Give a chance to update the contact address if connectivity has changed */ op->set_contact_address(destProxy->op->get_contact_address()); } else op->set_contact_address(nullptr); - return op->update(subject.c_str(), q->getParams()->getPrivate()->getNoUserConsent()); + return op->update(newSubject.c_str(), q->getParams()->getPrivate()->getNoUserConsent()); } void CallSessionPrivate::terminate () { @@ -827,6 +829,7 @@ void CallSession::startIncomingNotification () { int CallSession::startInvite (const Address *destination, const string &subject) { L_D(); + d->subject = subject; /* Try to be best-effort in giving real local or routable contact address */ d->setContactOp(); string destinationStr; @@ -889,7 +892,7 @@ LinphoneStatus CallSession::terminate (const LinphoneErrorInfo *ei) { return 0; } -LinphoneStatus CallSession::update (const CallSessionParams *csp) { +LinphoneStatus CallSession::update (const CallSessionParams *csp, const string &subject) { L_D(); LinphoneCallState nextState; LinphoneCallState initialState = d->state; @@ -897,7 +900,7 @@ LinphoneStatus CallSession::update (const CallSessionParams *csp) { return -1; if (d->currentParams == csp) lWarning() << "CallSession::update() is given the current params, this is probably not what you intend to do!"; - LinphoneStatus result = d->startUpdate(); + LinphoneStatus result = d->startUpdate(subject); if (result && (d->state != initialState)) { /* Restore initial state */ d->setState(initialState, "Restore initial state"); diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index a43331c2e..7f68e4fb7 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -49,9 +49,9 @@ public: virtual bool initiateOutgoing (); virtual void iterate (time_t currentRealTime, bool oneSecondElapsed); virtual void startIncomingNotification (); - virtual int startInvite (const Address *destination, const std::string &subject); + virtual int startInvite (const Address *destination, const std::string &subject = ""); LinphoneStatus terminate (const LinphoneErrorInfo *ei = nullptr); - LinphoneStatus update (const CallSessionParams *csp); + LinphoneStatus update (const CallSessionParams *csp, const std::string &subject = ""); CallSessionParams *getCurrentParams () const; LinphoneCallDir getDirection () const; diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index b9e75b401..18ff22f56 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -232,7 +232,7 @@ private: LinphoneStatus pause (); void setTerminated () override; LinphoneStatus startAcceptUpdate (LinphoneCallState nextState, const std::string &stateInfo) override; - LinphoneStatus startUpdate () override; + LinphoneStatus startUpdate (const std::string &subject = "") override; void terminate () override; void updateCurrentParams () const override; diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index 9137f16dd..d159a4dca 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -3706,7 +3706,7 @@ LinphoneStatus MediaSessionPrivate::startAcceptUpdate (LinphoneCallState nextSta return 0; } -LinphoneStatus MediaSessionPrivate::startUpdate () { +LinphoneStatus MediaSessionPrivate::startUpdate (const string &subject) { fillMulticastMediaAddresses(); if (!params->getPrivate()->getNoUserConsent()) makeLocalMediaDescription(); @@ -3714,7 +3714,7 @@ LinphoneStatus MediaSessionPrivate::startUpdate () { op->set_local_media_description(localDesc); else op->set_local_media_description(nullptr); - LinphoneStatus result = CallSessionPrivate::startUpdate(); + LinphoneStatus result = CallSessionPrivate::startUpdate(subject); if (core->sip_conf.sdp_200_ack) { /* We are NOT offering, set local media description after sending the call so that we are ready to * process the remote offer when it will arrive. */ @@ -4297,7 +4297,7 @@ void MediaSession::stopRecording () { d->recordActive = false; } -LinphoneStatus MediaSession::update (const MediaSessionParams *msp) { +LinphoneStatus MediaSession::update (const MediaSessionParams *msp, const string &subject) { L_D(); LinphoneCallState nextState; LinphoneCallState initialState = d->state; @@ -4316,7 +4316,7 @@ LinphoneStatus MediaSession::update (const MediaSessionParams *msp) { lInfo() << "Defer CallSession update to gather ICE candidates"; return 0; } - LinphoneStatus result = d->startUpdate(); + LinphoneStatus result = d->startUpdate(subject); if (result && (d->state != initialState)) { /* Restore initial state */ d->setState(initialState, "Restore initial state"); diff --git a/src/conference/session/media-session.h b/src/conference/session/media-session.h index 4de168815..60e2163e2 100644 --- a/src/conference/session/media-session.h +++ b/src/conference/session/media-session.h @@ -48,10 +48,10 @@ public: LinphoneStatus resume (); void sendVfuRequest (); void startIncomingNotification () override; - int startInvite (const Address *destination, const std::string &subject) override; + int startInvite (const Address *destination, const std::string &subject = "") override; void startRecording (); void stopRecording (); - LinphoneStatus update (const MediaSessionParams *msp); + LinphoneStatus update (const MediaSessionParams *msp, const std::string &subject = ""); void resetFirstVideoFrameDecoded (); LinphoneStatus takePreviewSnapshot (const std::string& file);