Commit 3d8d6431 authored by Andrea Gianarda's avatar Andrea Gianarda
Browse files

Fix crash of conference when creating it before the proxy config is available

Take into account conf-id when adding, searching and deleting conferences in the map
Do not set conf_ctx to NULL when callign linphone_core_terminate_conference
Test conference in server mode
Verify that 2 conferences with local participant enabled cannot be created at the same time
Do not update proxy config when creating a local conference
Add LINPHONE_PUBLIC to linphone_conference_params_new
parent 4eff297a
......@@ -78,22 +78,23 @@ Conference::~Conference() {
}
void Conference::setConferenceAddress (const ConferenceAddress &conferenceAddress) {
if (!conferenceAddress.isValid()) {
shared_ptr<CallSession> session = getMe()->getSession();
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 500, "Server internal error", NULL);
session->decline(ei);
linphone_error_info_unref(ei);
setState(ConferenceInterface::State::CreationFailed);
return;
}
if ((getState() == ConferenceInterface::State::Instantiated) || (getState() == ConferenceInterface::State::CreationPending)) {
if (!conferenceAddress.isValid()) {
shared_ptr<CallSession> session = getMe()->getSession();
LinphoneErrorInfo *ei = linphone_error_info_new();
linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 500, "Server internal error", NULL);
session->decline(ei);
linphone_error_info_unref(ei);
setState(ConferenceInterface::State::CreationFailed);
return;
}
if (getState() != ConferenceInterface::State::Instantiated) {
LinphonePrivate::Conference::setConferenceAddress(conferenceAddress);
lInfo() << "The Conference has been given the address " << conferenceAddress.asString() << ", now finalizing its creation";
} else {
lError() << "Cannot set the conference address of the Conference in state " << getState();
return;
}
LinphonePrivate::Conference::setConferenceAddress(conferenceAddress);
lInfo() << "The Conference has been given the address " << conferenceAddress.asString() << ", now finalizing its creation";
}
......@@ -261,19 +262,6 @@ void Conference::checkIfTerminated() {
}
int Conference::terminate () {
// Delete conference ID from proxy as the conference was terminated
LinphoneAddress * cConferenceAddress = linphone_address_new(getConferenceAddress().asString().c_str());
LinphoneProxyConfig * proxyCfg = linphone_core_lookup_known_proxy(getCore()->getCCore(), cConferenceAddress);
linphone_address_unref(cConferenceAddress);
char * contactAddressStr = sal_address_as_string(proxyCfg->op->getContactAddress());
Address contactAddress(contactAddressStr);
ms_free(contactAddressStr);
if (contactAddress.hasParam ("conf-id")) {
contactAddress.removeUriParam("conf-id");
proxyCfg->op->setContactAddress(contactAddress.getInternalAddress());
}
participants.clear();
return 0;
}
......@@ -316,7 +304,10 @@ void Conference::onConferenceTerminated (const IdentityAddress &addr) {
// Keep a reference to the conference to be able to set the state to Deleted
shared_ptr<Conference> ref = getSharedFromThis();
getCore()->deleteAudioVideoConference(ref);
// If core is in Global Shutdown state, then do not remove it from the map as it will be freed by Core::uninit()
if (linphone_core_get_global_state(getCore()->getCCore()) != LinphoneGlobalShutdown) {
getCore()->deleteAudioVideoConference(ref);
}
setState(ConferenceInterface::State::Deleted);
}
......@@ -392,22 +383,27 @@ LocalConference::LocalConference (
setState(ConferenceInterface::State::Instantiated);
mMixerSession.reset(new MixerSession(*core.get()));
char confId[6];
belle_sip_random_token(confId,sizeof(confId));
// Update proxy contact address to add conference ID
// Do not use myAddress directly as it may lack some parameter like gruu
LinphoneAddress * cAddress = linphone_address_new(myAddress.asString().c_str());
LinphoneProxyConfig * proxyCfg = linphone_core_lookup_known_proxy(core->getCCore(), cAddress);
char * contactAddressStr = sal_address_as_string(proxyCfg->op->getContactAddress());
char * contactAddressStr = nullptr;
if (proxyCfg && proxyCfg->op) {
contactAddressStr = sal_address_as_string(proxyCfg->op->getContactAddress());
} else {
contactAddressStr = ms_strdup(linphone_core_find_best_identity(core->getCCore(), const_cast<LinphoneAddress *>(cAddress)));
}
Address contactAddress(contactAddressStr);
ms_free(contactAddressStr);
char confId[6];
belle_sip_random_token(confId,sizeof(confId));
contactAddress.setUriParam("conf-id",confId);
proxyCfg->op->setContactAddress(contactAddress.getInternalAddress());
if (contactAddressStr) {
ms_free(contactAddressStr);
}
linphone_address_unref(cAddress);
setConferenceId(ConferenceId(contactAddress, contactAddress));
setConferenceAddress(contactAddress);
setState(ConferenceInterface::State::CreationPending);
}
LocalConference::~LocalConference() {
......@@ -422,11 +418,12 @@ LocalConference::~LocalConference() {
void LocalConference::setConferenceAddress (const ConferenceAddress &conferenceAddress) {
Conference::setConferenceAddress(conferenceAddress);
setState(ConferenceInterface::State::CreationPending);
}
void LocalConference::finalizeCreation() {
if (getState() == ConferenceInterface::State::CreationPending) {
const ConferenceAddress & conferenceAddress = getConferenceAddress ();
setConferenceId(ConferenceId(conferenceAddress, conferenceAddress));
#ifdef HAVE_ADVANCED_IM
if (eventHandler) {
eventHandler->setConference(this);
......@@ -488,6 +485,10 @@ int LocalConference::inviteAddresses (const list<const LinphoneAddress *> &addre
linphone_call_params_set_in_conference(new_params, TRUE);
const Address & conferenceAddress = getConferenceAddress ();
const string & confId = conferenceAddress.getUriParamValue("conf-id");
linphone_call_params_set_conference_id(new_params, confId.c_str());
call = linphone_core_invite_address_with_params(getCore()->getCCore(), address, new_params);
if (!call){
......@@ -525,6 +526,9 @@ bool LocalConference::addParticipant (std::shared_ptr<LinphonePrivate::Call> cal
confParams->enableLocalParticipant(true);
LinphoneCallState state = static_cast<LinphoneCallState>(call->getState());
bool localEndpointCanBeAdded = false;
const Address & conferenceAddress = getConferenceAddress ();
const string & confId = conferenceAddress.getUriParamValue("conf-id");
switch(state){
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
......@@ -532,6 +536,8 @@ bool LocalConference::addParticipant (std::shared_ptr<LinphonePrivate::Call> cal
case LinphoneCallPausing:
const_cast<LinphonePrivate::MediaSessionParamsPrivate *>(
L_GET_PRIVATE(call->getParams()))->setInConference(true);
const_cast<LinphonePrivate::MediaSessionParamsPrivate *>(
L_GET_PRIVATE(call->getParams()))->setConferenceId(confId);
break;
case LinphoneCallPaused:
{
......@@ -541,6 +547,8 @@ bool LocalConference::addParticipant (std::shared_ptr<LinphonePrivate::Call> cal
*/
const_cast<LinphonePrivate::MediaSessionParamsPrivate *>(
L_GET_PRIVATE(call->getParams()))->setInConference(true);
const_cast<LinphonePrivate::MediaSessionParamsPrivate *>(
L_GET_PRIVATE(call->getParams()))->setConferenceId(confId);
const_cast<LinphonePrivate::MediaSessionParams *>(
call->getParams())->enableVideo(getCurrentParams().videoEnabled());
// Conference resumes call that previously paused in order to add the participant
......@@ -553,6 +561,7 @@ bool LocalConference::addParticipant (std::shared_ptr<LinphonePrivate::Call> cal
LinphoneCallParams *params = linphone_core_create_call_params(getCore()->getCCore(), call->toC());
linphone_call_params_set_in_conference(params, TRUE);
linphone_call_params_enable_video(params, getCurrentParams().videoEnabled());
linphone_call_params_set_conference_id(params, confId.c_str());
linphone_call_update(call->toC(), params);
linphone_call_params_unref(params);
......@@ -940,8 +949,8 @@ RemoteConference::RemoteConference (
confParams->enableLocalParticipant(false);
setConferenceId(conferenceId);
// Store conference ID to retrieve later the local address when the focus call goes to StreamsRunning state
this->conferenceId = conferenceId;
setConferenceAddress(focus);
}
......@@ -1201,19 +1210,29 @@ void RemoteConference::onFocusCallSateChanged (LinphoneCallState state) {
list<std::shared_ptr<LinphonePrivate::Call>>::iterator it;
switch (state) {
case LinphoneCallConnected:
m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall->toC()));
it = m_pendingCalls.begin();
while (it != m_pendingCalls.end()) {
std::shared_ptr<LinphonePrivate::Call> pendingCall = *it;
LinphoneCallState pendingCallState = static_cast<LinphoneCallState>(pendingCall->getState());
if ((pendingCallState == LinphoneCallStreamsRunning) || (pendingCallState == LinphoneCallPaused)) {
it = m_pendingCalls.erase(it);
transferToFocus(pendingCall);
} else
it++;
case LinphoneCallUpdatedByRemote:
{
Address focusContactAddress(m_focusCall->getRemoteContact());
ConferenceId confId = getConferenceId();
Address peerAddress(confId.getPeerAddress());
if ((getState() == ConferenceInterface::State::CreationPending) && (focusContactAddress.hasUriParam("conf-id")) && (!peerAddress.hasUriParam("conf-id"))) {
m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall->toC()));
it = m_pendingCalls.begin();
while (it != m_pendingCalls.end()) {
std::shared_ptr<LinphonePrivate::Call> pendingCall = *it;
LinphoneCallState pendingCallState = static_cast<LinphoneCallState>(pendingCall->getState());
if ((pendingCallState == LinphoneCallStreamsRunning) || (pendingCallState == LinphoneCallPaused)) {
it = m_pendingCalls.erase(it);
transferToFocus(pendingCall);
} else
it++;
}
setConferenceId(ConferenceId(ConferenceAddress(m_focusContact), getConferenceId().getLocalAddress()));
m_focusCall->setConferenceId(focusContactAddress.getUriParamValue("conf-id"));
finalizeCreation();
}
setConferenceId(ConferenceId(ConferenceAddress(m_focusContact), getConferenceId().getLocalAddress()));
finalizeCreation();
}
break;
case LinphoneCallError:
reset();
......
......@@ -2431,14 +2431,12 @@ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEve
bctbx_free(resourceAddrStr);
const LinphoneAddress *from = linphone_event_get_from(lev);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ConferenceId(
LinphonePrivate::ConferenceId conferenceId = LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(from))
));
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(from))
));
);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(conferenceId);
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(conferenceId);
if (chatRoom) {
shared_ptr<ClientGroupChatRoom> cgcr;
......@@ -2490,14 +2488,15 @@ static void _linphone_core_conference_subscribe_received(LinphoneCore *lc, Linph
}
const LinphoneAddress *resource = linphone_event_get_resource(lev);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource))
));
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource))
));
char * resourceAddressStr = linphone_address_as_string(resource);
const ConferenceAddress conferenceAddress = ConferenceAddress(resourceAddressStr);
bctbx_free(resourceAddressStr);
LinphonePrivate::ConferenceId conferenceId = LinphonePrivate::ConferenceId(
ConferenceAddress(conferenceAddress),
ConferenceAddress(conferenceAddress)
);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(conferenceId);
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(conferenceId);
if (chatRoom)
static_pointer_cast<ServerGroupChatRoom>(chatRoom)->subscribeReceived(lev);
......@@ -2528,14 +2527,15 @@ static void _linphone_core_conference_subscription_state_changed (LinphoneCore *
}else{
/* This has to be done only when running as server */
const LinphoneAddress *resource = linphone_event_get_resource(lev);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource))
));
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(LinphonePrivate::ConferenceId(
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
ConferenceAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource))
));
char * resourceAddressStr = linphone_address_as_string(resource);
const ConferenceAddress conferenceAddress = ConferenceAddress(resourceAddressStr);
bctbx_free(resourceAddressStr);
LinphonePrivate::ConferenceId conferenceId = LinphonePrivate::ConferenceId(
ConferenceAddress(conferenceAddress),
ConferenceAddress(conferenceAddress)
);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(conferenceId);
shared_ptr<MediaConference::Conference> audioVideoConference = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findAudioVideoConference(conferenceId);
if (chatRoom)
L_GET_PRIVATE(static_pointer_cast<ServerGroupChatRoom>(chatRoom))->subscriptionStateChanged(lev, state);
else if (audioVideoConference)
......@@ -7862,7 +7862,6 @@ int linphone_core_terminate_conference(LinphoneCore *lc) {
return -1;
}
linphone_conference_terminate(lc->conf_ctx);
lc->conf_ctx = NULL;
return 0;
}
......
......@@ -89,6 +89,8 @@ void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params,
void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa);
bool_t linphone_call_params_get_in_conference(const LinphoneCallParams *params);
void linphone_call_params_set_in_conference(LinphoneCallParams *params, bool_t value);
const char * linphone_call_params_get_conference_id (const LinphoneCallParams *params);
void linphone_call_params_set_conference_id (LinphoneCallParams *params, const char * id);
bool_t linphone_call_params_get_internal_call_update(const LinphoneCallParams *params);
void linphone_call_params_set_internal_call_update(LinphoneCallParams *params, bool_t value);
bool_t linphone_call_params_implicit_rtcp_fb_enabled(const LinphoneCallParams *params);
......
......@@ -52,8 +52,16 @@ typedef enum {
* @{
*/
/**
* Create an object of type a #LinphoneConferenceParams.
* @param core The #LinphoneCore to pass to the constructor. @notnil
* @return The created #LinphoneConferenceParams. @notnil
*/
LINPHONE_PUBLIC LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core);
/**
* Take a reference on a #LinphoneConferencParams.
* Take a reference on a #LinphoneConferenceParams.
* @param params The #LinphoneConferenceParams to ref. @notnil
* @return The freshly refed #LinphoneConferenceParams. @notnil
*/
......@@ -65,6 +73,14 @@ LINPHONE_PUBLIC LinphoneConferenceParams *linphone_conference_params_ref(Linphon
*/
LINPHONE_PUBLIC void linphone_conference_params_unref(LinphoneConferenceParams *params);
/**
* Free a #LinphoneConferenceParams
* @param params #LinphoneConferenceParams to free @notnil
* @deprecated 17/03/2017 Use linphone_conference_params_unref() instead.
* @donotwrap
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_conference_params_free(LinphoneConferenceParams *params);
/**
* Clone a #LinphoneConferenceParams
* @param params The #LinphoneConferenceParams to clone @notnil
......@@ -204,14 +220,6 @@ LINPHONE_PUBLIC int linphone_conference_update_params(LinphoneConference *conf,
*/
LINPHONE_PUBLIC const LinphoneConferenceParams * linphone_conference_get_current_params(const LinphoneConference *conf);
/**
* Free a #LinphoneConferenceParams
* @param params #LinphoneConferenceParams to free @notnil
* @deprecated 17/03/2017 Use linphone_conference_params_unref() instead.
* @donotwrap
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_conference_params_free(LinphoneConferenceParams *params);
/**
* Get the conference subject
* @param conference The #LinphoneConference object. @notnil
......@@ -297,8 +305,6 @@ LINPHONE_PUBLIC int linphone_conference_enter(LinphoneConference *conference);
int linphone_conference_leave(LinphoneConference *conference);
LINPHONE_PUBLIC bool_t linphone_conference_is_in(const LinphoneConference *conference);
LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core);
LinphoneConference *linphone_local_conference_new(LinphoneCore *core, LinphoneAddress * addr);
LinphoneConference *linphone_local_conference_new_with_params(LinphoneCore *core, LinphoneAddress * addr, const LinphoneConferenceParams *params);
LinphoneConference *linphone_remote_conference_new(LinphoneCore *core, LinphoneAddress * addr);
......
......@@ -391,6 +391,14 @@ void linphone_call_params_set_received_fps (LinphoneCallParams *params, float va
// Private functions.
// =============================================================================
const char * linphone_call_params_get_conference_id (const LinphoneCallParams *params) {
return L_GET_PRIVATE_FROM_C_OBJECT(params)->getConferenceId();
}
void linphone_call_params_set_conference_id (LinphoneCallParams *params, const char * id) {
L_GET_PRIVATE_FROM_C_OBJECT(params)->setConferenceId(L_C_TO_STRING(id));
}
bool_t linphone_call_params_get_in_conference (const LinphoneCallParams *params) {
return L_GET_PRIVATE_FROM_C_OBJECT(params)->getInConference();
}
......
......@@ -350,6 +350,7 @@ void Call::removeFromConference(const Address & remoteContactAddress) {
if (conference) {
conference->setState(ConferenceInterface::State::TerminationPending);
setConference(nullptr);
setConferenceId("");
}
}
}
......@@ -408,6 +409,12 @@ void Call::onCallSessionStateChanged (const shared_ptr<CallSession> &session, Ca
Address remoteContactAddress(remoteContactAddressStr);
ms_free(remoteContactAddressStr);
// As the call is about to exit the conference, the contact address is missing the conference ID as well as isfocus parameter
if (!remoteContactAddress.hasUriParam("conf-id")) {
if (getConferenceId().empty() == false) {
remoteContactAddress.setUriParam("conf-id", getConferenceId());
}
}
if (!remoteContactAddress.hasParam("isfocus")) {
remoteContactAddress.setParam("isfocus");
removeFromConference(remoteContactAddress);
......@@ -436,13 +443,24 @@ void Call::onCallSessionStateChanged (const shared_ptr<CallSession> &session, Ca
ConferenceId remoteConferenceId = ConferenceId(remoteContactAddress, getLocalAddress());
shared_ptr<MediaConference::Conference> conference = getCore()->findAudioVideoConference(remoteConferenceId, false);
// Terminate conference is found
if (conference == nullptr) {
if ((conference == nullptr) && (getCore()->getCCore()->conf_ctx == nullptr)) {
// It is expected that the core of the remote conference is the participant one
shared_ptr<MediaConference::RemoteConference> remoteConf = std::shared_ptr<MediaConference::RemoteConference>(new MediaConference::RemoteConference(getCore(), getSharedFromThis(), remoteConferenceId, nullptr, ConferenceParams::create(getCore()->getCCore())), [](MediaConference::RemoteConference * c){c->unref();});
setConference(remoteConf->toC());
// Record conf-id to be used later when terminating the remote conference
if (remoteContactAddress.hasUriParam("conf-id")) {
setConferenceId(remoteContactAddress.getUriParamValue("conf-id"));
}
}
} else if (getConference()) {
// As the call is about to exit the conference, the contact address is missing the conference ID as well as isfocus parameter
if (!remoteContactAddress.hasUriParam("conf-id")) {
if (getConferenceId().empty() == false) {
remoteContactAddress.setUriParam("conf-id", getConferenceId());
}
}
if (!remoteContactAddress.hasParam("isfocus")) {
remoteContactAddress.setParam("isfocus");
removeFromConference(remoteContactAddress);
......@@ -470,13 +488,17 @@ void Call::onCallSessionStateChanged (const shared_ptr<CallSession> &session, Ca
ConferenceId remoteConferenceId = ConferenceId(remoteContactAddress, getLocalAddress());
shared_ptr<MediaConference::Conference> conference = getCore()->findAudioVideoConference(remoteConferenceId, false);
shared_ptr<MediaConference::RemoteConference> remoteConf = nullptr;
// Create remote conference if no conference with the expected ID is found in the database
if (conference == nullptr) {
// It is expected that the core of the remote conference is the participant one
remoteConf = std::shared_ptr<MediaConference::RemoteConference>(new MediaConference::RemoteConference(getCore(), getSharedFromThis(), remoteConferenceId, nullptr, ConferenceParams::create(getCore()->getCCore())), [](MediaConference::RemoteConference * c){c->unref();});
setConference(remoteConf->toC());
// Record conf-id to be used later when terminating the remote conference
if (remoteContactAddress.hasUriParam("conf-id")) {
setConferenceId(remoteContactAddress.getUriParamValue("conf-id"));
}
} else {
remoteConf = static_pointer_cast<MediaConference::RemoteConference>(conference);
}
......@@ -1031,6 +1053,14 @@ bool Call::isInConference () const {
return getActiveSession()->getPrivate()->isInConference();
}
void Call::setConferenceId (const std::string & conferenceId) {
return getActiveSession()->getPrivate()->setConferenceId(conferenceId);
}
std::string Call::getConferenceId () const {
return getActiveSession()->getPrivate()->getConferenceId();
}
bool Call::mediaInProgress () const {
return static_pointer_cast<const MediaSession>(getActiveSession())->mediaInProgress();
}
......
......@@ -168,6 +168,8 @@ public:
std::shared_ptr<Call> getTransferTarget () const;
LinphoneCallStats *getVideoStats () const;
bool isInConference () const;
std::string getConferenceId () const;
void setConferenceId (const std::string & conferenceId);
bool mediaInProgress () const;
void setAudioRoute (LinphoneAudioRoute route);
void setAuthenticationTokenVerified (bool value);
......
......@@ -38,6 +38,8 @@ public:
bool getInConference () const { return inConference; }
void setInConference (bool value) { inConference = value; }
const char * getConferenceId () const { return conferenceId.c_str(); }
void setConferenceId (const std::string value) { conferenceId = value; }
bool getInternalCallUpdate () const { return internalCallUpdate; }
void setInternalCallUpdate (bool value) { internalCallUpdate = value; }
bool getNoUserConsent () const { return noUserConsent; }
......@@ -62,6 +64,7 @@ private:
bool internalCallUpdate = false;
bool noUserConsent = false; /* When set to true an UPDATE request will be used instead of reINVITE */
SalCustomHeader *customHeaders = nullptr;
std::string conferenceId = "";
std::unordered_map<std::string, std::string> customContactParameters;
std::shared_ptr<CallSession> referer; /* In case call creation is consecutive to an incoming transfer, this points to the original call */
std::list<Content> customContents;
......
......@@ -32,6 +32,7 @@ void CallSessionParamsPrivate::clone (const CallSessionParamsPrivate *src) {
sessionName = src->sessionName;
privacy = src->privacy;
inConference = src->inConference;
conferenceId = src->conferenceId;
internalCallUpdate = src->internalCallUpdate;
noUserConsent = src->noUserConsent;
/* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. */
......@@ -101,6 +102,7 @@ CallSessionParams &CallSessionParams::operator= (const CallSessionParams &other)
void CallSessionParams::initDefault (const std::shared_ptr<Core> &core, LinphoneCallDir dir) {
L_D();
d->inConference = false;
d->conferenceId = "";
d->privacy = LinphonePrivacyDefault;
setProxyConfig(NULL);
}
......
......@@ -46,6 +46,8 @@ public:
SalCallOp * getOp () const { return op; }
bool isBroken () const { return broken; }
bool isInConference () const;
const std::string getConferenceId () const;
void setConferenceId (const std::string id);
void setParams (CallSessionParams *csp);
void setReferPending (bool value) { referPending = value; }
void setTransferTarget (std::shared_ptr<CallSession> session) { transferTarget = session; }
......
......@@ -31,6 +31,7 @@
#include "core/core-p.h"
#include "logger/logger.h"
#include "conference_private.h"
#include "private.h"
using namespace std;
......@@ -220,6 +221,14 @@ bool CallSessionPrivate::isInConference () const {
return params->getPrivate()->getInConference();
}
const std::string CallSessionPrivate::getConferenceId () const {
return params->getPrivate()->getConferenceId();
}
void CallSessionPrivate::setConferenceId (const std::string id) {
params->getPrivate()->setConferenceId(id);
}
// -----------------------------------------------------------------------------
void CallSessionPrivate::abort (const string &errorMsg) {
......@@ -682,10 +691,11 @@ LinphoneStatus CallSessionPrivate::startUpdate (const string &subject) {
Address contactAddress(contactAddressStr);
ms_free(contactAddressStr);
destProxy->op->setContactAddress(contactAddress.getInternalAddress());
q->updateContactAddress(contactAddress);
op->setContactAddress(contactAddress.getInternalAddress());
destProxy->op->setContactAddress(contactAddress.getInternalAddress());
} else
op->setContactAddress(nullptr);
return op->update(newSubject.c_str(), q->getParams()->getPrivate()->getNoUserConsent());
......@@ -748,6 +758,18 @@ void CallSessionPrivate::setContactOp () {
char * contactAddressStr = linphone_address_as_string(contact);
Address contactAddress(contactAddressStr);
ms_free(contactAddressStr);
if (isInConference()) {
const string confId = getConferenceId();
if (confId.empty() == false) {
contactAddress.setUriParam("conf-id", confId);
}
std::shared_ptr<MediaConference::Conference> conference = q->getCore()->findAudioVideoConference(ConferenceId(contactAddress, contactAddress));
if (conference) {
// Change conference address in order to add GRUU to it
conference->setConferenceAddress(contactAddress);
}
}
q->updateContactAddress (contactAddress);
op->setContactAddress(contactAddress.getInternalAddress());
linphone_address_unref(contact);
......@@ -1497,15 +1519,29 @@ const CallSessionParams * CallSession::getParams () const {
return d->params;
}
void CallSession::updateContactAddress (Address & contactAddress) const {
void CallSession::updateContactAddress (Address & contactAddress) {
L_D();
if (d->isInConference() && (!contactAddress.hasParam("isfocus"))) {
// If in conference and contact address doesn't have isfocus
contactAddress.setParam("isfocus");
} else if (!d->isInConference() && contactAddress.hasParam("isfocus")) {
if (d->isInConference()) {
// Add conference ID
if (!contactAddress.hasUriParam("conf-id")) {
const string confId = d->getConferenceId();
if (confId.empty() == false) {
contactAddress.setUriParam("conf-id", confId);
}
}
if (!contactAddress.hasParam("isfocus")) {
// If in conference and contact address doesn't have isfocus
contactAddress.setParam("isfocus");
}
} else if (!d->isInConference()) {
// If not in conference and contact address has isfocus
contactAddress.removeParam("isfocus");
if (contactAddress.hasUriParam("conf-id")) {
contactAddress.removeUriParam("conf-id");
}
if (contactAddress.hasParam("isfocus")) {
contactAddress.removeParam("isfocus");
}