Commit 6c7c5627 authored by Simon Morlat's avatar Simon Morlat

Implement deferred ICE reinvite response when the ICE session isn't yet completed.

parent 3a0bcc67
...@@ -134,6 +134,7 @@ protected: ...@@ -134,6 +134,7 @@ protected:
bool broken = false; bool broken = false;
bool deferIncomingNotification = false; bool deferIncomingNotification = false;
bool deferUpdate = false; bool deferUpdate = false;
bool deferUpdateInternal = false;
bool needLocalIpRefresh = false; bool needLocalIpRefresh = false;
bool nonOpError = false; /* Set when the LinphoneErrorInfo was set at higher level than sal */ bool nonOpError = false; /* Set when the LinphoneErrorInfo was set at higher level than sal */
bool notifyRinging = true; bool notifyRinging = true;
......
...@@ -467,9 +467,10 @@ void CallSessionPrivate::updated (bool isUpdate) { ...@@ -467,9 +467,10 @@ void CallSessionPrivate::updated (bool isUpdate) {
void CallSessionPrivate::updatedByRemote () { void CallSessionPrivate::updatedByRemote () {
L_Q(); L_Q();
setState(CallSession::State::UpdatedByRemote,"Call updated by remote"); setState(CallSession::State::UpdatedByRemote,"Call updated by remote");
if (deferUpdate) { if (deferUpdate || deferUpdateInternal) {
if (state == CallSession::State::UpdatedByRemote) if (state == CallSession::State::UpdatedByRemote && !deferUpdateInternal){
lInfo() << "CallSession [" << q << "]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call CallSession::acceptUpdate() later"; lInfo() << "CallSession [" << q << "]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call linphone_call_accept_update() later";
}
} else { } else {
if (state == CallSession::State::UpdatedByRemote) if (state == CallSession::State::UpdatedByRemote)
q->acceptUpdate(nullptr); q->acceptUpdate(nullptr);
......
...@@ -254,7 +254,6 @@ private: ...@@ -254,7 +254,6 @@ private:
int sendDtmf (); int sendDtmf ();
void stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1); void stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1);
private: private:
static const std::string ecStateStore; static const std::string ecStateStore;
static const int ecStateMaxLen; static const int ecStateMaxLen;
...@@ -325,6 +324,7 @@ private: ...@@ -325,6 +324,7 @@ private:
bool automaticallyPaused = false; bool automaticallyPaused = false;
bool pausedByApp = false; bool pausedByApp = false;
bool recordActive = false; bool recordActive = false;
bool incomingIceReinvitePending = false;
std::string onHoldFile; std::string onHoldFile;
......
...@@ -382,6 +382,8 @@ void MediaSessionPrivate::updated (bool isUpdate) { ...@@ -382,6 +382,8 @@ void MediaSessionPrivate::updated (bool isUpdate) {
CallSessionPrivate::updated(isUpdate); CallSessionPrivate::updated(isUpdate);
} }
void MediaSessionPrivate::updating (bool isUpdate) { void MediaSessionPrivate::updating (bool isUpdate) {
L_Q(); L_Q();
SalMediaDescription *rmd = op->get_remote_media_description(); SalMediaDescription *rmd = op->get_remote_media_description();
...@@ -702,6 +704,10 @@ shared_ptr<Participant> MediaSessionPrivate::getMe () const { ...@@ -702,6 +704,10 @@ shared_ptr<Participant> MediaSessionPrivate::getMe () const {
void MediaSessionPrivate::setState (CallSession::State newState, const string &message) { void MediaSessionPrivate::setState (CallSession::State newState, const string &message) {
L_Q(); L_Q();
SalMediaDescription *rmd;
lInfo()<<"MediaSessionPrivate::setState";
/* Take a ref on the session otherwise it might get destroyed during the call to setState */ /* Take a ref on the session otherwise it might get destroyed during the call to setState */
shared_ptr<CallSession> sessionRef = q->getSharedFromThis(); shared_ptr<CallSession> sessionRef = q->getSharedFromThis();
if ((newState != state) && (newState != CallSession::State::StreamsRunning)) if ((newState != state) && (newState != CallSession::State::StreamsRunning))
...@@ -709,6 +715,21 @@ void MediaSessionPrivate::setState (CallSession::State newState, const string &m ...@@ -709,6 +715,21 @@ void MediaSessionPrivate::setState (CallSession::State newState, const string &m
CallSessionPrivate::setState(newState, message); CallSessionPrivate::setState(newState, message);
if (listener) if (listener)
listener->onCallSessionStateChangedForReporting(q->getSharedFromThis()); listener->onCallSessionStateChangedForReporting(q->getSharedFromThis());
switch(newState){
case CallSession::State::UpdatedByRemote:
/*Handle specifically the case of an incoming ICE-concluded reINVITE*/
lInfo()<<"Checking for ICE reINVITE";
rmd = op->get_remote_media_description();
if (iceAgent && rmd != nullptr && iceAgent->checkIceReinviteNeedsDeferedResponse(rmd)){
deferUpdate = true;
deferUpdateInternal = true;
incomingIceReinvitePending = true;
lInfo()<<"CallSession [" << q << "]: ICE reinvite received, but one or more check-lists are not completed. Response will be sent later, when ICE has completed";
}
break;
default:
break;
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -2191,11 +2212,14 @@ void MediaSessionPrivate::handleIceEvents (OrtpEvent *ev) { ...@@ -2191,11 +2212,14 @@ void MediaSessionPrivate::handleIceEvents (OrtpEvent *ev) {
OrtpEventData *evd = ortp_event_get_data(ev); OrtpEventData *evd = ortp_event_get_data(ev);
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
if (iceAgent->hasCompletedCheckList()) { if (iceAgent->hasCompletedCheckList()) {
/* At least one ICE session has succeeded, so perform a call update */ /* The ICE session has succeeded, so perform a call update */
if (iceAgent->isControlling() && q->getCurrentParams()->getPrivate()->getUpdateCallWhenIceCompleted()) { if (iceAgent->isControlling() && q->getCurrentParams()->getPrivate()->getUpdateCallWhenIceCompleted()) {
MediaSessionParams newParams(*getParams()); MediaSessionParams newParams(*getParams());
newParams.getPrivate()->setInternalCallUpdate(true); newParams.getPrivate()->setInternalCallUpdate(true);
q->update(&newParams); q->update(&newParams);
}else if (!iceAgent->isControlling() && incomingIceReinvitePending){
q->acceptUpdate(nullptr);
incomingIceReinvitePending = false;
} }
startDtlsOnAllStreams(); startDtlsOnAllStreams();
} }
......
...@@ -738,4 +738,35 @@ void IceAgent::updateIceStateInCallStatsForStream (LinphoneCallStats *stats, Ice ...@@ -738,4 +738,35 @@ void IceAgent::updateIceStateInCallStatsForStream (LinphoneCallStats *stats, Ice
} }
} }
bool IceAgent::checkIceReinviteNeedsDeferedResponse(SalMediaDescription *md){
int i,j;
IceCheckList *cl;
if (!iceSession) return false;
if (ice_session_state(iceSession) != IS_Running ) return false;
for (i = 0; i < md->nb_streams; i++) {
SalStreamDescription *stream = &md->streams[i];
cl = ice_session_check_list(iceSession, i);
if (cl==NULL) continue;
if (stream->ice_mismatch == TRUE) {
return false;
}
if (stream->rtp_port == 0) {
continue;
}
if (ice_check_list_state(cl) != ICL_Running) continue;
for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; j++) {
const SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[j];
if (remote_candidate->addr[0] != '\0') return true;
}
}
return false;
}
LINPHONE_END_NAMESPACE LINPHONE_END_NAMESPACE
...@@ -66,6 +66,11 @@ public: ...@@ -66,6 +66,11 @@ public:
void updateFromRemoteMediaDescription (const SalMediaDescription *localDesc, const SalMediaDescription *remoteDesc, bool isOffer); void updateFromRemoteMediaDescription (const SalMediaDescription *localDesc, const SalMediaDescription *remoteDesc, bool isOffer);
void updateIceStateInCallStats (); void updateIceStateInCallStats ();
void updateLocalMediaDescriptionFromIce (SalMediaDescription *desc); void updateLocalMediaDescriptionFromIce (SalMediaDescription *desc);
/*
* Checks if an incoming offer with ICE needs a delayed answer, because the ice session hasn't completed yet with
* connecvity checks.
*/
bool checkIceReinviteNeedsDeferedResponse(SalMediaDescription *md);
private: private:
void addLocalIceCandidates (int family, const char *addr, IceCheckList *audioCl, IceCheckList *videoCl, IceCheckList *textCl); void addLocalIceCandidates (int family, const char *addr, IceCheckList *audioCl, IceCheckList *videoCl, IceCheckList *textCl);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment