diff --git a/src/call.cpp b/src/call.cpp index de068038d242671007bd1b0bd420813c9d26141f..47cedd596ab97e0b84837907e5a0f336a46dc51c 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -124,10 +124,13 @@ Call::validTransition(CallState newState) bool Call::setState(CallState state) { + std::lock_guard<std::mutex> lock(callMutex_); if (not validTransition(state)) { - assert((int)callState_ < enum_class_size<CallState>() && (int)state < enum_class_size<CallState>()); - //RING_ERR("Invalid call state transition from %s to %s", states[callState_], states[state]); + assert((int)callState_ < enum_class_size<CallState>() + && (int)state < enum_class_size<CallState>()); + RING_ERR("Invalid attempted call state transition from %d to %d", + callState_, state); return false; } diff --git a/src/call.h b/src/call.h index 88f90323b6a37aab9eca734136b7a99045a62cd6..767950a243e45e7e497215cd9d899a47aafb685d 100644 --- a/src/call.h +++ b/src/call.h @@ -271,13 +271,13 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> { * Put a call on hold * @return bool True on success */ - virtual void onhold() = 0; + virtual bool onhold() = 0; /** * Resume a call from hold state * @return bool True on success */ - virtual void offhold() = 0; + virtual bool offhold() = 0; /** * mute/unmute a media of a call diff --git a/src/iax/iaxcall.cpp b/src/iax/iaxcall.cpp index 7332f36e8f4cbe49dffe9968c664a937cfd672fc..38fb846ba40a6b8e712add3c1e4e4416cf4863b2 100644 --- a/src/iax/iaxcall.cpp +++ b/src/iax/iaxcall.cpp @@ -194,7 +194,7 @@ IAXCall::attendedTransfer(const std::string& /*targetID*/) return false; // TODO } -void +bool IAXCall::onhold() { Manager::instance().getRingBufferPool().unBindAll(getCallId()); @@ -204,12 +204,14 @@ IAXCall::onhold() iax_quelch_moh(session, true); } - setState(Call::CallState::HOLD); + return setState(Call::CallState::HOLD); } -void +bool IAXCall::offhold() { + bool success = false; + Manager::instance().addStream(*this); { @@ -217,9 +219,10 @@ IAXCall::offhold() iax_unquelch(session); } - setState(Call::CallState::ACTIVE); + if (success = setState(Call::CallState::ACTIVE)) + Manager::instance().startAudioDriverStream(); - Manager::instance().startAudioDriverStream(); + return success; } void diff --git a/src/iax/iaxcall.h b/src/iax/iaxcall.h index a84599aef8a2d72e87056a16711fe9e22e5d3daa..1ace687369333dd03136a6c375d18b0a86ef3b3c 100644 --- a/src/iax/iaxcall.h +++ b/src/iax/iaxcall.h @@ -127,9 +127,9 @@ class IAXCall : public Call bool attendedTransfer(const std::string& to); - void onhold(); + bool onhold(); - void offhold(); + bool offhold(); //TODO: implement mute for IAX void muteMedia(const std::string& mediaType, bool isMuted) {} diff --git a/src/manager.cpp b/src/manager.cpp index 802a07c24727c3e5b58fd70058b723240b6cbc5b..d686c6eeffd15a4091692a45297f8435720f1a5f 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -628,26 +628,29 @@ Manager::onHoldCall(const std::string& callId) if (auto call = getCallFromCallID(callId)) { try { - call->onhold(); - removeStream(*call); // Unbind calls in main buffer + if (result = call->onhold()) + removeStream(*call); // Unbind calls in main buffer } catch (const VoipLinkException &e) { RING_ERR("%s", e.what()); result = false; } + } else { RING_DBG("CallID %s doesn't exist in call onHold", callId.c_str()); return false; } - // Remove call from teh queue if it was still there - removeWaitingCall(callId); + if (result) { + // Remove call from the queue if it was still there + removeWaitingCall(callId); - // keeps current call id if the action is not holding this call or a new outgoing call - // this could happen in case of a conference - if (current_call_id == callId) - unsetCurrentCall(); + // keeps current call id if the action is not holding this call + // or a new outgoing call. This could happen in case of a conference + if (current_call_id == callId) + unsetCurrentCall(); - emitSignal<DRing::CallSignal::StateChange>(callId, "HOLD", 0); + emitSignal<DRing::CallSignal::StateChange>(callId, "HOLD", 0); + } return result; } diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index 4f099f6a3e8f6446c136b02f44d784dabd62a1a7..efcd8dcb53a1cea9a354335d18ae7d870f389c0d 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -585,11 +585,11 @@ SIPCall::attendedTransfer(const std::string& to) return transferCommon(&dst); } -void +bool SIPCall::onhold() { if (not setState(CallState::HOLD)) - return; + return false; stopAllMedia(); @@ -597,30 +597,35 @@ SIPCall::onhold() if (SIPSessionReinvite() != PJ_SUCCESS) RING_WARN("Reinvite failed"); } + + return true; } -void +bool SIPCall::offhold() { + bool success = false; auto& account = getSIPAccount(); try { if (account.isStunEnabled()) - internalOffHold([&] { updateSDPFromSTUN(); }); + success = internalOffHold([&] { updateSDPFromSTUN(); }); else - internalOffHold([] {}); + success = internalOffHold([] {}); } catch (const SdpException &e) { RING_ERR("%s", e.what()); throw VoipLinkException("SDP issue in offhold"); } + + return success; } -void +bool SIPCall::internalOffHold(const std::function<void()>& sdp_cb) { if (not setState(CallState::ACTIVE)) - return; + return false; sdp_cb(); @@ -628,8 +633,11 @@ SIPCall::internalOffHold(const std::function<void()>& sdp_cb) if (SIPSessionReinvite() != PJ_SUCCESS) { RING_WARN("Reinvite failed, resuming hold"); onhold(); + return false; } } + + return true; } void diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h index 46b05b29205abc8677b8df7946c888157e7acf52..06ac8cbf3c5791fcdfa40243a834f26d8a94b805 100644 --- a/src/sip/sipcall.h +++ b/src/sip/sipcall.h @@ -152,9 +152,9 @@ class SIPCall : public Call bool attendedTransfer(const std::string& to); - void onhold(); + bool onhold(); - void offhold(); + bool offhold(); void switchInput(const std::string& resource); @@ -221,7 +221,7 @@ class SIPCall : public Call */ bool transferCommon(pj_str_t *dst); - void internalOffHold(const std::function<void()> &SDPUpdateFunc); + bool internalOffHold(const std::function<void()> &SDPUpdateFunc); int SIPSessionReinvite();