Commit 008ec55b authored by Ghislain MARY's avatar Ghislain MARY

Handle call repair in CallSession and MediaSession classes.

parent 52f13d34
......@@ -54,34 +54,11 @@ using namespace LinphonePrivate;
static void register_failure(SalOp *op);
static LinphoneCall * look_for_broken_call_to_replace(LinphonePrivate::SalOp *h, LinphoneCore *lc) {
const bctbx_list_t *calls = linphone_core_get_calls(lc);
const bctbx_list_t *it = calls;
while (it != NULL) {
#if 0
LinphoneCall *replaced_call = NULL;
LinphoneCall *call = (LinphoneCall *)bctbx_list_get_data(it);
SalOp *replaced_op = sal_call_get_replaces(h);
if (replaced_op) replaced_call = (LinphoneCall*)sal_op_get_user_pointer(replaced_op);
if ((call->broken && sal_call_compare_op(h, call->op))
|| ((replaced_call == call) && (strcmp(sal_op_get_from(h), sal_op_get_from(replaced_op)) == 0) && (strcmp(sal_op_get_to(h), sal_op_get_to(replaced_op)) == 0))) {
return call;
}
#endif
it = bctbx_list_next(it);
}
return NULL;
}
static void call_received(SalCallOp *h) {
/* Look if this INVITE is for a call that has already been notified but broken because of network failure */
LinphoneCore *lc = reinterpret_cast<LinphoneCore *>(h->get_sal()->get_user_pointer());
LinphoneCall *replacedCall = look_for_broken_call_to_replace(h, lc);
if (replacedCall) {
linphone_call_replace_op(replacedCall, h);
if (L_GET_PRIVATE_FROM_C_OBJECT(lc)->inviteReplacesABrokenCall(h))
return;
}
LinphoneAddress *fromAddr = nullptr;
const char *pAssertedId = sal_custom_header_find(h->get_recv_custom_header(), "P-Asserted-Identity");
......@@ -314,13 +291,12 @@ static void call_released(SalOp *op) {
}
static void call_cancel_done(SalOp *op) {
#if 0
LinphoneCall *call = (LinphoneCall *)sal_op_get_user_pointer(op);
if (call->reinvite_on_cancel_response_requested == TRUE) {
call->reinvite_on_cancel_response_requested = FALSE;
linphone_call_reinvite_to_recover_from_connection_loss(call);
LinphonePrivate::CallSession *session = reinterpret_cast<LinphonePrivate::CallSession *>(op->get_user_pointer());
if (!session) {
ms_warning("Cancel done reported on already terminated CallSession");
return;
}
#endif
L_GET_PRIVATE(session)->cancelDone();
}
static void auth_failure(SalOp *op, SalAuthInfo* info) {
......
......@@ -6140,39 +6140,15 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable,
if (!lc->sip_network_reachable){
linphone_core_invalidate_friend_subscriptions(lc);
lc->sal->reset_transports();
/*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/
#if 0
bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_set_broken);
#endif
}
}
void linphone_core_repair_calls(LinphoneCore *lc){
#if 0
if (lc->calls && lp_config_get_int(lc->config, "sip", "repair_broken_calls", 1) && lc->media_network_reachable){
/*if we are registered and there were broken calls due to a past network disconnection, attempt to repair them*/
bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_repair_if_broken);
}
#endif
}
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.
ms_message("Media network reachability state is now [%s]",is_media_reachable?"UP":"DOWN");
lc->media_network_reachable=is_media_reachable;
if (!lc->media_network_reachable){
/*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/
#if 0
bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_set_broken);
#endif
}else{
if (lp_config_get_int(lc->config, "net", "recreate_sockets_when_network_is_up", 0)){
#if 0
bctbx_list_for_each(lc->calls, (MSIterateFunc)linphone_call_refresh_sockets);
#endif
}
linphone_core_repair_calls(lc);
if (lc->media_network_reachable){
if (lc->bw_controller){
ms_bandwidth_controller_reset_state(lc->bw_controller);
}
......
......@@ -54,9 +54,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to);
void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state);
LinphonePlayer *linphone_call_build_player(LinphoneCall*call);
void linphone_call_refresh_sockets(LinphoneCall *call);
void linphone_call_replace_op(LinphoneCall *call, LinphonePrivate::SalOp *op);
void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call);
LinphonePrivate::SalCallOp *linphone_call_get_op(const LinphoneCall *call);
LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call);
......@@ -335,9 +332,6 @@ LinphoneEcCalibratorStatus ec_calibrator_get_status(EcCalibrator *ecc);
void ec_calibrator_destroy(EcCalibrator *ecc);
void linphone_call_set_broken(LinphoneCall *call);
void linphone_call_repair_if_broken(LinphoneCall *call);
void linphone_core_repair_calls(LinphoneCore *lc);
int linphone_core_preempt_sound_resources(LinphoneCore *lc);
int _linphone_call_pause(LinphoneCall *call);
......
......@@ -1310,10 +1310,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat
cfg->state=state;
}
if (lc){
if (lc)
linphone_core_notify_registration_state_changed(lc,cfg,state,message);
linphone_core_repair_calls(lc);
}
} else {
/*state already reported*/
}
......
......@@ -18,6 +18,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "c-wrapper/c-wrapper.h"
#include "core/core-p.h"
#include "private.h"
#include "linphone/wrapper_utils.h"
......@@ -100,6 +103,7 @@ void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall
}
void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyRegistrationStateChanged(cfg, cstate, message);
NOTIFY_IF_EXIST(registration_state_changed, lc,cfg,cstate,message);
cleanup_dead_vtable_refs(lc);
}
......@@ -239,6 +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);
NOTIFY_IF_EXIST(network_reachable, lc,reachable);
cleanup_dead_vtable_refs(lc);
}
......
......@@ -94,6 +94,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
content/file-content.h
content/file-transfer-content.h
core/core-accessor.h
core/core-listener.h
core/core-p.h
core/core.h
core/paths/paths.h
......
......@@ -319,188 +319,15 @@ int linphone_call_start_invite (LinphoneCall *call, const LinphoneAddress *desti
return 0;
}
void linphone_call_replace_op (LinphoneCall *call, LinphonePrivate::SalOp *op) {
#if 0
SalOp *oldop = call->op;
LinphoneCallState oldstate = linphone_call_get_state(call);
call->op = op;
sal_op_set_user_pointer(call->op, call);
sal_call_set_local_media_description(call->op, call->localdesc);
switch (linphone_call_get_state(call)) {
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
sal_call_notify_ringing(call->op, (linphone_call_get_state(call) == LinphoneCallIncomingEarlyMedia) ? TRUE : FALSE);
break;
case LinphoneCallConnected:
case LinphoneCallStreamsRunning:
sal_call_accept(call->op);
break;
default:
ms_warning("linphone_call_replace_op(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
break;
}
switch (oldstate) {
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
sal_op_set_user_pointer(oldop, nullptr); /* To make the call does not get terminated by terminating this op. */
/* Do not terminate a forked INVITE */
if (sal_call_get_replaces(op)) {
sal_call_terminate(oldop);
} else {
sal_op_kill_dialog(oldop);
}
break;
case LinphoneCallConnected:
case LinphoneCallStreamsRunning:
sal_call_terminate(oldop);
sal_op_kill_dialog(oldop);
break;
default:
break;
}
sal_op_release(oldop);
#endif
}
// =============================================================================
// Private functions.
// =============================================================================
#if 0
static void linphone_call_repair_by_invite_with_replaces (LinphoneCall *call) {
const char *call_id = sal_op_get_call_id(call->op);
const char *from_tag = sal_call_get_local_tag(call->op);
const char *to_tag = sal_call_get_remote_tag(call->op);
sal_op_kill_dialog(call->op);
linphone_call_create_op(call);
sal_call_set_replaces(call->op, call_id, from_tag, to_tag);
linphone_call_start_invite(call, nullptr);
}
#endif
MediaStream *linphone_call_get_stream (LinphoneCall *call, LinphoneStreamType type) {
return L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(type);
}
void linphone_call_set_broken (LinphoneCall *call) {
#if 0
switch(call->state){
/*for all the early states, we prefer to drop the call*/
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia:
/*during the early states, the SAL layer reports the failure from the dialog or transaction layer,
* hence, there is nothing special to do*/
//break;
case LinphoneCallStreamsRunning:
case LinphoneCallUpdating:
case LinphoneCallPausing:
case LinphoneCallResuming:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
case LinphoneCallUpdatedByRemote:
/*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*/
call->broken = TRUE;
call->need_localip_refresh = TRUE;
break;
default:
ms_error("linphone_call_set_broken() unimplemented case.");
break;
}
#endif
}
void linphone_call_reinvite_to_recover_from_connection_loss (LinphoneCall *call) {
#if 0
LinphoneCallParams *params;
ms_message("LinphoneCall[%p] is going to be updated (reINVITE) in order to recover from lost connectivity", call);
if (call->ice_session){
ice_session_reset(call->ice_session, IR_Controlling);
}
params = linphone_core_create_call_params(call->core, call);
linphone_call_update(call, params);
linphone_call_params_unref(params);
#endif
}
void linphone_call_repair_if_broken (LinphoneCall *call) {
#if 0
SalErrorInfo sei;
if (!call->broken) return;
if (!call->core->media_network_reachable) return;
memset(&sei, 0, sizeof(sei));
/*Make sure that the proxy from which we received this call, or to which we routed this call is registered first*/
if (call->dest_proxy){
/*in all other cases, ie no proxy config, or a proxy config for which no registration was requested, we can start the
* call repair immediately.*/
if (linphone_proxy_config_register_enabled(call->dest_proxy)
&& linphone_proxy_config_get_state(call->dest_proxy) != LinphoneRegistrationOk) return;
}
switch (call->state){
case LinphoneCallUpdating:
case LinphoneCallPausing:
if (sal_call_dialog_request_pending(call->op)) {
/* Need to cancel first re-INVITE as described in section 5.5 of RFC 6141 */
sal_call_cancel_invite(call->op);
call->reinvite_on_cancel_response_requested = TRUE;
}
break;
case LinphoneCallStreamsRunning:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
if (!sal_call_dialog_request_pending(call->op)) {
linphone_call_reinvite_to_recover_from_connection_loss(call);
}
break;
case LinphoneCallUpdatedByRemote:
if (sal_call_dialog_request_pending(call->op)) {
sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, nullptr, nullptr);
sal_call_decline_with_error_info(call->op, &sei,nullptr);
}
linphone_call_reinvite_to_recover_from_connection_loss(call);
break;
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
sal_call_cancel_invite(call->op);
call->reinvite_on_cancel_response_requested = TRUE;
break;
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallOutgoingRinging:
linphone_call_repair_by_invite_with_replaces(call);
break;
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
/* Keep the call broken until a forked INVITE is received from the server. */
break;
default:
ms_warning("linphone_call_repair_if_broken(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
call->broken = FALSE;
break;
}
sal_error_info_reset(&sei);
#endif
}
void linphone_call_refresh_sockets (LinphoneCall *call) {
#if 0
int i;
for (i=0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
MSMediaStreamSessions *mss = &call->sessions[i];
if (mss->rtp_session){
rtp_session_refresh_sockets(mss->rtp_session);
}
}
#endif
}
LinphonePrivate::SalCallOp * linphone_call_get_op (const LinphoneCall *call) {
return L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp();
}
......
......@@ -29,7 +29,7 @@
LINPHONE_BEGIN_NAMESPACE
class CallSessionPrivate : public ObjectPrivate {
class CallSessionPrivate : public ObjectPrivate, public CoreListener {
public:
CallSessionPrivate () = default;
......@@ -43,16 +43,19 @@ public:
CallSessionParams *getCurrentParams () const { return currentParams; }
LinphoneProxyConfig * getDestProxy () const { return destProxy; }
SalCallOp * getOp () const { return op; }
bool isBroken () const { return broken; }
void setParams (CallSessionParams *csp);
virtual void abort (const std::string &errorMsg);
virtual void accepted ();
void ackBeingSent (LinphoneHeaders *headers);
virtual void ackReceived (LinphoneHeaders *headers);
void cancelDone ();
virtual bool failure ();
void infoReceived (SalBodyHandler *bodyHandler);
void pingReply ();
virtual void remoteRinging ();
void replaceOp (SalCallOp *newOp);
virtual void terminated ();
void updated (bool isUpdate);
void updatedByRemote ();
......@@ -77,6 +80,10 @@ protected:
void setContactOp ();
// CoreListener
void onNetworkReachable (bool reachable) override;
void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) override;
private:
void completeLog ();
void createOp ();
......@@ -84,6 +91,10 @@ private:
LinphoneAddress * getFixedContact () const;
virtual void reinviteToRecoverFromConnectionLoss ();
void repairByInviteWithReplaces ();
void repairIfBroken ();
protected:
CallSessionListener *listener = nullptr;
......@@ -107,9 +118,12 @@ protected:
bool pingReplied = false;
int pingTime = 0;
bool broken = false;
bool deferIncomingNotification = false;
bool deferUpdate = false;
bool needLocalIpRefresh = false;
bool nonOpError = false; /* Set when the LinphoneErrorInfo was set at higher level than sal */
bool reinviteOnCancelResponseRequested = false;
private:
L_DECLARE_PUBLIC(CallSession);
......
......@@ -26,7 +26,7 @@
#include "conference/params/call-session-params-p.h"
#include "conference/session/call-session-p.h"
#include "conference/session/call-session.h"
#include "core/core.h"
#include "core/core-p.h"
#include "logger/logger.h"
......@@ -241,6 +241,13 @@ void CallSessionPrivate::ackReceived (LinphoneHeaders *headers) {
listener->onAckReceived(q->getSharedFromThis(), headers);
}
void CallSessionPrivate::cancelDone () {
if (reinviteOnCancelResponseRequested) {
reinviteOnCancelResponseRequested = false;
reinviteToRecoverFromConnectionLoss();
}
}
bool CallSessionPrivate::failure () {
L_Q();
const SalErrorInfo *ei = op->get_error_info();
......@@ -338,6 +345,47 @@ void CallSessionPrivate::remoteRinging () {
setState(LinphoneCallOutgoingRinging, "Remote ringing");
}
void CallSessionPrivate::replaceOp (SalCallOp *newOp) {
L_Q();
SalCallOp *oldOp = op;
LinphoneCallState oldState = state;
op = newOp;
op->set_user_pointer(q);
op->set_local_media_description(oldOp->get_local_media_description());
switch (state) {
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
op->notify_ringing((state == LinphoneCallIncomingEarlyMedia) ? true : false);
break;
case LinphoneCallConnected:
case LinphoneCallStreamsRunning:
op->accept();
break;
default:
lWarning() << "CallSessionPrivate::replaceOp(): don't know what to do in state [" << linphone_call_state_to_string(state) << "]";
break;
}
switch (oldState) {
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
op->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();
else
oldOp->kill_dialog();
break;
case LinphoneCallConnected:
case LinphoneCallStreamsRunning:
oldOp->terminate();
oldOp->kill_dialog();
break;
default:
break;
}
oldOp->release();
}
void CallSessionPrivate::terminated () {
switch (state) {
case LinphoneCallEnd:
......@@ -640,6 +688,45 @@ void CallSessionPrivate::setContactOp () {
// -----------------------------------------------------------------------------
void CallSessionPrivate::onNetworkReachable (bool reachable) {
if (reachable) {
repairIfBroken();
} else {
switch(state) {
// For all the early states, we prefer to drop the call
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia:
// During the early states, the SAL layer reports the failure from the dialog or transaction layer,
// hence, there is nothing special to do
case LinphoneCallStreamsRunning:
case LinphoneCallUpdating:
case LinphoneCallPausing:
case LinphoneCallResuming:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
case LinphoneCallUpdatedByRemote:
// 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;
}
}
}
void CallSessionPrivate::onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) {
repairIfBroken();
}
// -----------------------------------------------------------------------------
void CallSessionPrivate::completeLog () {
L_Q();
log->duration = computeDuration(); /* Store duration since connected */
......@@ -699,11 +786,96 @@ LinphoneAddress * CallSessionPrivate::getFixedContact () const {
return result;
}
// -----------------------------------------------------------------------------
void CallSessionPrivate::reinviteToRecoverFromConnectionLoss () {
L_Q();
lInfo() << "CallSession [" << q << "] is going to be updated (reINVITE) in order to recover from lost connectivity";
q->update(params);
}
void CallSessionPrivate::repairByInviteWithReplaces () {
L_Q();
const char *callId = op->get_call_id();
const char *fromTag = op->get_local_tag();
const char *toTag = op->get_remote_tag();
op->kill_dialog();
createOp();
op->set_replaces(callId, fromTag, toTag);
q->startInvite(nullptr);
}
void CallSessionPrivate::repairIfBroken () {
L_Q();
LinphoneCore *lc = q->getCore()->getCCore();
LinphoneConfig *config = linphone_core_get_config(lc);
if (!lp_config_get_int(config, "sip", "repair_broken_calls", 1) || !lc->media_network_reachable || !broken)
return;
// If we are registered and this session has been broken due to a past network disconnection,
// attempt to repair it
// Make sure that the proxy from which we received this call, or to which we routed this call is registered first
if (destProxy) {
// In all other cases, ie no proxy config, or a proxy config for which no registration was requested,
// we can start the call session repair immediately.
if (linphone_proxy_config_register_enabled(destProxy)
&& (linphone_proxy_config_get_state(destProxy) != LinphoneRegistrationOk))
return;
}
SalErrorInfo sei;
memset(&sei, 0, sizeof(sei));
switch (state) {
case LinphoneCallUpdating:
case LinphoneCallPausing:
if (op->dialog_request_pending()) {
// Need to cancel first re-INVITE as described in section 5.5 of RFC 6141
op->cancel_invite();
reinviteOnCancelResponseRequested = true;
}
break;
case LinphoneCallStreamsRunning:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
if (!op->dialog_request_pending())
reinviteToRecoverFromConnectionLoss();
break;
case LinphoneCallUpdatedByRemote:
if (op->dialog_request_pending()) {
sal_error_info_set(&sei, SalReasonServiceUnavailable, "SIP", 0, nullptr, nullptr);
op->decline_with_error_info(&sei, nullptr);
}
reinviteToRecoverFromConnectionLoss();
break;
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
op->cancel_invite();
reinviteOnCancelResponseRequested = true;
break;
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallOutgoingRinging:
repairByInviteWithReplaces();
break;
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallIncomingReceived:
// Keep the call broken until a forked INVITE is received from the server
break;
default:
lWarning() << "CallSessionPrivate::repairIfBroken: don't know what to do in state ["
<< linphone_call_state_to_string(state);
broken = false;
break;
}
sal_error_info_reset(&sei);
}
// =============================================================================
CallSession::CallSession (const shared_ptr<Core> &core, const CallSessionParams *params, CallSessionListener *listener)
: Object(*new CallSessionPrivate), CoreAccessor(core) {
L_D();
getCore()->getPrivate()->registerListener(d);
d->listener = listener;
if (params)
d->setParams(new CallSessionParams(*params));
......@@ -713,11 +885,13 @@ CallSession::CallSession (const shared_ptr<Core> &core, const CallSessionParams
CallSession::CallSession (CallSessionPrivate &p, const shared_ptr<Core> &core) : Object(p), CoreAccessor(core) {
L_D();
getCore()->getPrivate()->registerListener(d);
d->init();
}
CallSession::~CallSession () {
L_D();
getCore()->getPrivate()->unregisterListener(d);
if (d->currentParams)
delete d->currentParams;
if (d->params)
......
......@@ -25,6 +25,7 @@
#include "conference/conference.h"
#include "conference/params/call-session-params.h"
#include "conference/session/call-session-listener.h"
#include "core/core-listener.h"
#include "sal/call-op.h"
// =============================================================================
......@@ -41,6 +42,7 @@ class LINPHONE_PUBLIC CallSession : public Object, public CoreAccessor {
friend class ClientGroupChatRoom;
friend class ClientGroupChatRoomPrivate;
friend class Conference;
friend class CorePrivate;
friend class ServerGroupChatRoom;
friend class ServerGroupChatRoomPrivate;
......
......@@ -87,6 +87,9 @@ public:
SalCallOp * getOp () const { return op; }
void setAudioMuted (bool value) { audioMuted = value; }
// CoreListener
void onNetworkReachable (bool reachable) override;
private:
static OrtpJitterBufferAlgorithm jitterBufferNameToAlgo (const std::string &name);
......@@ -235,6 +238,9 @@ private:
void accept (const MediaSessionParams *params);
LinphoneStatus acceptUpdate (const CallSessionParams *csp, LinphoneCallState nextState, const std::string &stateInfo) override;
void refreshSockets ();
void reinviteToRecoverFromConnectionLoss () override;
#ifdef VIDEO_ENABLED
void videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args);
#endif // ifdef VIDEO_ENABLED
......
......@@ -539,6 +539,18 @@ int MediaSessionPrivate::getStreamIndex (MediaStream *ms) const {
// -----------------------------------------------------------------------------
void MediaSessionPrivate::onNetworkReachable (bool reachable) {
L_Q();
if (reachable) {
LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore());
if (lp_config_get_int(config, "net", "recreate_sockets_when_network_is_up", 0))
refreshSockets();
}
CallSessionPrivate::onNetworkReachable(reachable);
}
// -----------------------------------------------------------------------------
OrtpJitterBufferAlgorithm MediaSessionPrivate::jitterBufferNameToAlgo (const string &name) {
if (name == "basic") return OrtpJitterBufferBasic;
if (name == "rls") return OrtpJitterBufferRecursiveLeastSquare;
......@@ -3693,9 +3705,7 @@ LinphoneStatus MediaSessionPrivate::pause () {
lError() << "No reason to pause this call, it is already paused or inactive";
return -1;
}
#if 0
call->broken = FALSE;
#endif
broken = false;
setState(LinphoneCallPausing, "Pausing call");
makeLocalMediaDescription();
op->set_local_media_description(localDesc);
......@@ -3945,6 +3955,24 @@ LinphoneStatus MediaSessionPrivate::acceptUpdate (const CallSessionParams *csp,
// -----------------------------------------------------------------------------
void MediaSessionPrivate::refreshSockets () {
for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
MSMediaStreamSessions *mss = &sessions[i];
if (mss->rtp_session)
rtp_session_refresh_sockets(mss->rtp_session);
}
}
void MediaSessionPrivate::reinviteToRecoverFromConnectionLoss () {
L_Q();
lInfo() << "MediaSession [" << q << "] is going to be updated (reINVITE) in order to recover from lost connectivity";
if (iceAgent->hasSession())
iceAgent->resetSession(IR_Controlling);
q->update(getParams());
}
// -----------------------------------------------------------------------------
#ifdef VIDEO_ENABLED
void MediaSessionPrivate::videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args) {
L_Q();
......@@ -4261,9 +4289,7 @@ LinphoneStatus MediaSession::resume () {
lInfo() << "Resuming MediaSession " << this;