diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 8a0c45e02..729538720 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -6125,6 +6125,8 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, static void set_media_network_reachable(LinphoneCore* lc, bool_t is_media_reachable){ if (lc->media_network_reachable==is_media_reachable) return; // no change, ignore. + lc->network_reachable_to_be_notified=TRUE; + ms_message("Media network reachability state is now [%s]",is_media_reachable?"UP":"DOWN"); lc->media_network_reachable=is_media_reachable; diff --git a/coreapi/vtables.c b/coreapi/vtables.c index 2088a8296..13472609c 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -243,7 +243,7 @@ void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguri } void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) { - L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyNetworkReachable(!!reachable); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyNetworkReachable(!!lc->sip_network_reachable, lc->media_network_reachable); NOTIFY_IF_EXIST(network_reachable, lc,reachable); cleanup_dead_vtable_refs(lc); } diff --git a/src/conference/handlers/remote-conference-event-handler-p.h b/src/conference/handlers/remote-conference-event-handler-p.h index cef4e3e16..8f5bbe4ef 100644 --- a/src/conference/handlers/remote-conference-event-handler-p.h +++ b/src/conference/handlers/remote-conference-event-handler-p.h @@ -38,7 +38,7 @@ private: void unsubscribe (); // CoreListener - void onNetworkReachable (bool reachable) override; + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) override; ChatRoomId chatRoomId; diff --git a/src/conference/handlers/remote-conference-event-handler.cpp b/src/conference/handlers/remote-conference-event-handler.cpp index d90373d8a..101dd77e2 100644 --- a/src/conference/handlers/remote-conference-event-handler.cpp +++ b/src/conference/handlers/remote-conference-event-handler.cpp @@ -200,8 +200,8 @@ void RemoteConferenceEventHandlerPrivate::unsubscribe () { // ----------------------------------------------------------------------------- -void RemoteConferenceEventHandlerPrivate::onNetworkReachable (bool reachable) { - if (!reachable) +void RemoteConferenceEventHandlerPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (!sipNetworkReachable) unsubscribe(); } diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index 9edfb49da..6a542dec3 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -86,10 +86,11 @@ protected: virtual void terminate (); virtual void updateCurrentParams () const; + void setBroken (); void setContactOp (); // CoreListener - void onNetworkReachable (bool reachable) override; + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) override; private: diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index 8be74bd97..6be65f12a 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -379,7 +379,7 @@ void CallSessionPrivate::replaceOp (SalCallOp *newOp) { switch (oldState) { case CallSession::State::IncomingEarlyMedia: case CallSession::State::IncomingReceived: - op->set_user_pointer(nullptr); // In order for the call session to not get terminated by terminating this op + oldOp->set_user_pointer(nullptr); // In order for the call session to not get terminated by terminating this op // Do not terminate a forked INVITE if (op->get_replaces()) oldOp->terminate(); @@ -668,6 +668,35 @@ void CallSessionPrivate::updateCurrentParams () const {} // ----------------------------------------------------------------------------- +void CallSessionPrivate::setBroken () { + switch (state) { + // For all the early states, we prefer to drop the call + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + // During the early states, the SAL layer reports the failure from the dialog or transaction layer, + // hence, there is nothing special to do + case CallSession::State::StreamsRunning: + case CallSession::State::Updating: + case CallSession::State::Pausing: + case CallSession::State::Resuming: + case CallSession::State::Paused: + case CallSession::State::PausedByRemote: + case CallSession::State::UpdatedByRemote: + // During these states, the dialog is established. A failure of a transaction is not expected to close it. + // Instead we have to repair the dialog by sending a reINVITE + broken = true; + needLocalIpRefresh = true; + break; + default: + lError() << "CallSessionPrivate::setBroken(): unimplemented case"; + break; + } +} + void CallSessionPrivate::setContactOp () { L_Q(); SalAddress *salAddress = nullptr; @@ -684,37 +713,11 @@ void CallSessionPrivate::setContactOp () { // ----------------------------------------------------------------------------- -void CallSessionPrivate::onNetworkReachable (bool reachable) { - if (reachable) { +void CallSessionPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (sipNetworkReachable) repairIfBroken(); - } else { - switch(state) { - // For all the early states, we prefer to drop the call - case CallSession::State::OutgoingInit: - case CallSession::State::OutgoingProgress: - case CallSession::State::OutgoingRinging: - case CallSession::State::OutgoingEarlyMedia: - case CallSession::State::IncomingReceived: - case CallSession::State::IncomingEarlyMedia: - // During the early states, the SAL layer reports the failure from the dialog or transaction layer, - // hence, there is nothing special to do - case CallSession::State::StreamsRunning: - case CallSession::State::Updating: - case CallSession::State::Pausing: - case CallSession::State::Resuming: - case CallSession::State::Paused: - case CallSession::State::PausedByRemote: - case CallSession::State::UpdatedByRemote: - // During these states, the dialog is established. A failure of a transaction is not expected to close it. - // Instead we have to repair the dialog by sending a reINVITE - broken = true; - needLocalIpRefresh = true; - break; - default: - lError() << "CallSessionPrivate::onNetworkReachable(): unimplemented case"; - break; - } - } + else + setBroken(); } void CallSessionPrivate::onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) { diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 8d7aecad5..7f49055f7 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -109,7 +109,7 @@ public: SalMediaDescription *getResultDesc () const { return resultDesc; } // CoreListener - void onNetworkReachable (bool reachable) override; + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; private: static OrtpJitterBufferAlgorithm jitterBufferNameToAlgo (const std::string &name); diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index 3f2f680e2..f91dd6b89 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -629,14 +629,16 @@ void MediaSessionPrivate::stopStreams () { // ----------------------------------------------------------------------------- -void MediaSessionPrivate::onNetworkReachable (bool reachable) { +void MediaSessionPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { L_Q(); - if (reachable) { + if (mediaNetworkReachable) { LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); if (lp_config_get_int(config, "net", "recreate_sockets_when_network_is_up", 0)) refreshSockets(); + } else { + setBroken(); } - CallSessionPrivate::onNetworkReachable(reachable); + CallSessionPrivate::onNetworkReachable(sipNetworkReachable, mediaNetworkReachable); } // ----------------------------------------------------------------------------- diff --git a/src/core/core-listener.h b/src/core/core-listener.h index 4c55f0d36..95bb9caae 100644 --- a/src/core/core-listener.h +++ b/src/core/core-listener.h @@ -30,7 +30,7 @@ class CoreListener { public: virtual ~CoreListener () = default; - virtual void onNetworkReachable (bool reachable) {} + virtual void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) {} virtual void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) {} }; diff --git a/src/core/core-p.h b/src/core/core-p.h index aa035cbde..fd8f2459b 100644 --- a/src/core/core-p.h +++ b/src/core/core-p.h @@ -39,7 +39,7 @@ public: void unregisterListener (CoreListener *listener); void uninit (); - void notifyNetworkReachable (bool reachable); + void notifyNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable); void notifyRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message); int addCall (const std::shared_ptr &call); diff --git a/src/core/core.cpp b/src/core/core.cpp index ce39aac35..8df379fa7 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -79,9 +79,9 @@ void CorePrivate::uninit () { // ----------------------------------------------------------------------------- -void CorePrivate::notifyNetworkReachable (bool reachable) { +void CorePrivate::notifyNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { for (const auto &listener : listeners) - listener->onNetworkReachable(reachable); + listener->onNetworkReachable(sipNetworkReachable, mediaNetworkReachable); } void CorePrivate::notifyRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const string &message) {