diff --git a/coreapi/private.h b/coreapi/private.h index fe4ae5c48..228339482 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -438,7 +438,6 @@ void linphone_core_stop_waiting(LinphoneCore *lc); int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy); int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination/* = NULL if to be taken from the call log */); -int linphone_call_restart_invite(LinphoneCall *call); /* * param automatic_offering aims is to take into account previous answer for video in case of automatic re-invite. * Purpose is to avoid to re-ask video previously declined */ diff --git a/src/address/address.h b/src/address/address.h index 9e5d90cc6..94c2e4ea2 100644 --- a/src/address/address.h +++ b/src/address/address.h @@ -29,6 +29,7 @@ LINPHONE_BEGIN_NAMESPACE class AddressPrivate; class LINPHONE_PUBLIC Address : public ClonableObject { + friend class CallSession; friend class ClientGroupChatRoom; public: diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp index 4d0278ed4..f7d51ac93 100644 --- a/src/c-wrapper/api/c-call.cpp +++ b/src/c-wrapper/api/c-call.cpp @@ -179,19 +179,7 @@ void linphone_call_update_local_media_description_from_ice_or_upnp (LinphoneCall void linphone_call_make_local_media_description (LinphoneCall *call) {} -void linphone_call_create_op (LinphoneCall *call) { -#if 0 - if (call->op) sal_op_release(call->op); - call->op=sal_op_new(call->core->sal); - sal_op_set_user_pointer(call->op,call); - if (linphone_call_params_get_referer(call->params)) - sal_call_set_referer(call->op,linphone_call_params_get_referer(call->params)->op); - linphone_configure_op(call->core,call->op,call->log->to,linphone_call_params_get_custom_headers(call->params),FALSE); - if (linphone_call_params_get_privacy(call->params) != LinphonePrivacyDefault) - sal_op_set_privacy(call->op,(SalPrivacyMask)linphone_call_params_get_privacy(call->params)); - /*else privacy might be set by proxy */ -#endif -} +void linphone_call_create_op (LinphoneCall *call) {} void linphone_call_set_state (LinphoneCall *call, LinphoneCallState cstate, const char *message) {} @@ -884,39 +872,7 @@ LinphoneStatus linphone_call_terminate_with_error_info (LinphoneCall *call , con } LinphoneStatus linphone_call_redirect (LinphoneCall *call, const char *redirect_uri) { -#if 0 - char *real_url = nullptr; - LinphoneCore *lc; - LinphoneAddress *real_parsed_url; - SalErrorInfo sei; - - if (call->state != LinphoneCallIncomingReceived) { - ms_error("Bad state for call redirection."); - return -1; - } - - lc = linphone_call_get_core(call); - real_parsed_url = linphone_core_interpret_url(lc, redirect_uri); - if (!real_parsed_url) { - /* Bad url */ - ms_error("Bad redirect URI: %s", redirect_uri ? redirect_uri : "NULL"); - return -1; - } - - memset(&sei, 0, sizeof(sei)); - real_url = linphone_address_as_string(real_parsed_url); - sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, nullptr, nullptr); - sal_call_decline_with_error_info(call->op, &sei, real_url); - ms_free(real_url); - linphone_error_info_set(call->ei, nullptr, LinphoneReasonMovedPermanently, 302, "Call redirected", nullptr); - call->non_op_error = TRUE; - terminate_call(call); - linphone_address_unref(real_parsed_url); - sal_error_info_reset(&sei); - return 0; -#else - return 0; -#endif + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->redirect(redirect_uri); } LinphoneStatus linphone_call_decline (LinphoneCall *call, LinphoneReason reason) { diff --git a/src/call/call.cpp b/src/call/call.cpp index 369f2bfd7..ba0f12951 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -267,6 +267,11 @@ LinphoneStatus Call::pause () { return static_cast(d->getActiveSession().get())->pause(); } +LinphoneStatus Call::redirect (const std::string &redirectUri) { + L_D(); + return d->getActiveSession()->redirect(redirectUri); +} + LinphoneStatus Call::resume () { L_D(); return static_cast(d->getActiveSession().get())->resume(); diff --git a/src/call/call.h b/src/call/call.h index b42780fb1..2cf6a08da 100644 --- a/src/call/call.h +++ b/src/call/call.h @@ -53,6 +53,7 @@ public: LinphoneStatus decline (LinphoneReason reason); LinphoneStatus decline (const LinphoneErrorInfo *ei); LinphoneStatus pause (); + LinphoneStatus redirect (const std::string &redirectUri); LinphoneStatus resume (); void sendVfuRequest (); void startRecording (); diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index 924aed37a..18f1fdf83 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -61,6 +61,7 @@ protected: virtual void handleIncomingReceivedStateInIncomingNotification (); virtual bool isReadyForInvite () const; bool isUpdateAllowed (LinphoneCallState &nextState) const; + virtual int restartInvite (); virtual void setReleased (); virtual void setTerminated (); virtual LinphoneStatus startAcceptUpdate (LinphoneCallState nextState, const std::string &stateInfo); @@ -72,6 +73,7 @@ protected: private: void completeLog (); + void createOp (); void createOpTo (const LinphoneAddress *to); LinphoneAddress * getFixedContact () const; diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index 3bb20e55e..2397cbe6b 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -255,9 +255,7 @@ bool CallSessionPrivate::failure () { linphone_address_unref(log->to); log->to = linphone_address_new(url); ms_free(url); -#if 0 - linphone_call_restart_invite(call); -#endif + restartInvite(); return true; } } @@ -514,6 +512,12 @@ bool CallSessionPrivate::isUpdateAllowed (LinphoneCallState &nextState) const { return true; } +int CallSessionPrivate::restartInvite () { + L_Q(); + createOp(); + return q->startInvite(nullptr, subject); +} + /* * Called internally when reaching the Released state, to perform cleanups to break circular references. **/ @@ -617,6 +621,10 @@ void CallSessionPrivate::completeLog () { linphone_core_report_call_log(core, log); } +void CallSessionPrivate::createOp () { + createOpTo(log->to); +} + void CallSessionPrivate::createOpTo (const LinphoneAddress *to) { L_Q(); if (op) @@ -794,6 +802,38 @@ void CallSession::iterate (time_t currentRealTime, bool oneSecondElapsed) { } } +LinphoneStatus CallSession::redirect (const string &redirectUri) { + L_D(); + LinphoneAddress *realParsedAddr = linphone_core_interpret_url(d->core, redirectUri.c_str()); + if (!realParsedAddr) { + /* Bad url */ + lError() << "Bad redirect URI: " << redirectUri; + return -1; + } + char *realParsedUri = linphone_address_as_string(realParsedAddr); + Address redirectAddr(realParsedUri); + bctbx_free(realParsedUri); + linphone_address_unref(realParsedAddr); + return redirect(redirectAddr); +} + +LinphoneStatus CallSession::redirect (const Address &redirectAddr) { + L_D(); + if (d->state != LinphoneCallIncomingReceived) { + lError() << "Bad state for CallSession redirection"; + return -1; + } + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + sal_error_info_set(&sei, SalReasonRedirect, "SIP", 0, nullptr, nullptr); + d->op->decline_with_error_info(&sei, redirectAddr.getPrivate()->getInternalAddress()); + linphone_error_info_set(d->ei, nullptr, LinphoneReasonMovedPermanently, 302, "Call redirected", nullptr); + d->nonOpError = true; + d->terminate(); + sal_error_info_reset(&sei); + return 0; +} + void CallSession::startIncomingNotification () { L_D(); if (d->listener) diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index 7f68e4fb7..52ae7e1d3 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -48,6 +48,8 @@ public: virtual void initiateIncoming (); virtual bool initiateOutgoing (); virtual void iterate (time_t currentRealTime, bool oneSecondElapsed); + LinphoneStatus redirect (const std::string &redirectUri); + LinphoneStatus redirect (const Address &redirectAddr); virtual void startIncomingNotification (); virtual int startInvite (const Address *destination, const std::string &subject = ""); LinphoneStatus terminate (const LinphoneErrorInfo *ei = nullptr); diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 18ff22f56..31f8da816 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -230,6 +230,7 @@ private: void handleIncomingReceivedStateInIncomingNotification () override; bool isReadyForInvite () const override; LinphoneStatus pause (); + int restartInvite () override; void setTerminated () override; LinphoneStatus startAcceptUpdate (LinphoneCallState nextState, const std::string &stateInfo) override; LinphoneStatus startUpdate (const std::string &subject = "") override; diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index d159a4dca..505821151 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -264,27 +264,21 @@ bool MediaSessionPrivate::failure () { if (i == 0) lInfo() << "Retrying CallSession [" << q << "] with SAVP"; params->enableAvpf(false); -#if 0 - linphone_call_restart_invite(call); -#endif + restartInvite(); return true; } else if (!linphone_core_is_media_encryption_mandatory(core)) { if (i == 0) lInfo() << "Retrying CallSession [" << q << "] with AVP"; params->setMediaEncryption(LinphoneMediaEncryptionNone); memset(localDesc->streams[i].crypto, 0, sizeof(localDesc->streams[i].crypto)); -#if 0 - linphone_call_restart_invite(call); -#endif + restartInvite(); return true; } } else if (params->avpfEnabled()) { if (i == 0) lInfo() << "Retrying CallSession [" << q << "] with AVP"; params->enableAvpf(false); -#if 0 - linphone_call_restart_invite(call); -#endif + restartInvite(); return true; } } @@ -3684,6 +3678,12 @@ LinphoneStatus MediaSessionPrivate::pause () { return 0; } +int MediaSessionPrivate::restartInvite () { + stopStreams(); + initializeStreams(); + return CallSessionPrivate::restartInvite(); +} + void MediaSessionPrivate::setTerminated () { freeResources(); CallSessionPrivate::setTerminated();