Commit d356e08f authored by Guillaume Roguez's avatar Guillaume Roguez

daemon: move onhold/offhold API to Call class

Refs #51555

Change-Id: If42f6b60cd2d924a4ae750ddc6af63fe0d0eb68f
parent d75e0940
......@@ -266,6 +266,18 @@ class Call : public Recordable {
*/
virtual bool attendedTransfer(const std::string& to) = 0;
/**
* Put a call on hold
* @return bool True on success
*/
virtual void onhold() = 0;
/**
* Resume a call from hold state
* @return bool True on success
*/
virtual void offhold() = 0;
private:
bool validTransition(CallState newState);
......
......@@ -181,3 +181,31 @@ IAXCall::attendedTransfer(const std::string& /*targetID*/)
{
return false; // TODO
}
void
IAXCall::onhold()
{
Manager::instance().getMainBuffer().unBindAll(getCallId());
{
std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX);
iax_quelch_moh(session, true);
}
setState(Call::HOLD);
}
void
IAXCall::offhold()
{
Manager::instance().addStream(getCallId());
{
std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX);
iax_unquelch(session);
}
setState(Call::ACTIVE);
Manager::instance().startAudioDriverStream();
}
......@@ -90,6 +90,10 @@ class IAXCall : public Call {
bool attendedTransfer(const std::string& to);
void onhold();
void offhold();
private:
NON_COPYABLE(IAXCall);
......
......@@ -330,47 +330,6 @@ IAXVoIPLink::peerHungup(const std::string& id)
removeIaxCall(id);
}
void
IAXVoIPLink::onhold(const std::string& id)
{
Manager::instance().getMainBuffer().unBindAll(id);
{
std::lock_guard<std::mutex> lock(iaxCallMapMutex_);
auto call = getIAXCall(id);
if (!call)
throw VoipLinkException("Could not find call");
{
std::lock_guard<std::mutex> lock(mutexIAX);
iax_quelch_moh(call->session, true);
}
call->setState(Call::HOLD);
}
}
void
IAXVoIPLink::offhold(const std::string& id)
{
Manager::instance().addStream(id);
{
std::lock_guard<std::mutex> lock(iaxCallMapMutex_);
auto call = getIAXCall(id);
if (!call)
throw VoipLinkException("Could not find call");
{
std::lock_guard<std::mutex> lock(mutexIAX);
iax_unquelch(call->session);
}
call->setState(Call::ACTIVE);
}
Manager::instance().startAudioDriverStream();
}
void
IAXVoIPLink::carryingDTMFdigits(const std::string& id, char code)
{
......
......@@ -133,22 +133,6 @@ class IAXVoIPLink : public VoIPLink {
*/
virtual void cancel(const std::string& /*id*/) {}
/**
* Put a call on hold
* @param id The ID of the call
* @return bool true on success
* false otherwise
*/
virtual void onhold(const std::string& id);
/**
* Put a call off hold
* @param id The ID of the call
* @return bool true on success
* false otherwise
*/
virtual void offhold(const std::string& id);
/**
* Send DTMF
* @param id The ID of the call
......
......@@ -534,12 +534,12 @@ bool ManagerImpl::onHoldCall(const std::string& callId)
std::string current_call_id(getCurrentCallId());
try {
std::string account_id(getAccountFromCall(callId));
if (account_id.empty()) {
DEBUG("Account ID %s or callid %s doesn't exist in call onHold", account_id.c_str(), callId.c_str());
if (auto call = getCallFromCallID(callId)) {
call->onhold();
} else {
DEBUG("CallID %s doesn't exist in call onHold", callId.c_str());
return false;
}
getAccountLink(account_id)->onhold(callId);
} catch (const VoipLinkException &e) {
ERROR("%s", e.what());
result = false;
......@@ -583,7 +583,7 @@ bool ManagerImpl::offHoldCall(const std::string& callId)
try {
if (auto call = getCallFromCallID(callId))
call->getVoIPLink()->offhold(callId);
call->offhold();
else
result = false;
} catch (const VoipLinkException &e) {
......
......@@ -36,6 +36,9 @@
#include "logger.h" // for _debug
#include "sdp.h"
#include "manager.h"
#include "audio/audiortp/audio_rtp_factory.h" // for AudioRtpFactoryException
#ifdef SFL_VIDEO
#include "client/videomanager.h"
......@@ -129,100 +132,6 @@ SIPSessionReinvite(SIPCall *call)
return !PJ_SUCCESS;
}
void
SIPCall::offhold(const std::function<void()> &SDPUpdateFunc)
{
if (not setState(Call::ACTIVE))
return;
if (local_sdp_ == NULL)
throw SdpException("Could not find sdp session");
std::vector<sfl::AudioCodec*> sessionMedia(local_sdp_->getSessionAudioMedia());
if (sessionMedia.empty()) {
WARN("Session media is empty");
return;
}
std::vector<sfl::AudioCodec*> audioCodecs;
for (auto & i : sessionMedia) {
if (!i)
continue;
// Create a new instance for this codec
sfl::AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(i->getPayloadType());
if (ac == NULL) {
ERROR("Could not instantiate codec %d", i->getPayloadType());
throw std::runtime_error("Could not instantiate codec");
}
audioCodecs.push_back(ac);
}
if (audioCodecs.empty()) {
throw std::runtime_error("Could not instantiate any codecs");
}
audiortp_.initConfig();
audiortp_.initSession();
// Invoke closure
SDPUpdateFunc();
audiortp_.restoreLocalContext();
audiortp_.initLocalCryptoInfoOnOffHold();
audiortp_.start(audioCodecs);
local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv");
local_sdp_->removeAttributeFromLocalAudioMedia("sendonly");
local_sdp_->addAttributeToLocalAudioMedia("sendrecv");
#ifdef SFL_VIDEO
local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv");
local_sdp_->removeAttributeFromLocalVideoMedia("sendonly");
local_sdp_->removeAttributeFromLocalVideoMedia("inactive");
local_sdp_->addAttributeToLocalVideoMedia("sendrecv");
#endif
if (SIPSessionReinvite(this) != PJ_SUCCESS) {
WARN("Reinvite failed, resuming hold");
onhold();
}
}
void
SIPCall::onhold()
{
if (not setState(Call::HOLD))
return;
audiortp_.saveLocalContext();
audiortp_.stop();
#ifdef SFL_VIDEO
videortp_.stop();
#endif
if (!local_sdp_)
throw SdpException("Could not find sdp session");
local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv");
local_sdp_->removeAttributeFromLocalAudioMedia("sendonly");
local_sdp_->addAttributeToLocalAudioMedia("sendonly");
#ifdef SFL_VIDEO
local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv");
local_sdp_->removeAttributeFromLocalVideoMedia("inactive");
local_sdp_->addAttributeToLocalVideoMedia("inactive");
#endif
if (SIPSessionReinvite(this) != PJ_SUCCESS)
WARN("Reinvite failed");
}
VoIPLink*
SIPCall::getVoIPLink() const
{ return &SIPVoIPLink::instance(); }
......@@ -523,3 +432,120 @@ SIPCall::attendedTransfer(const std::string& /*to*/)
return transferCommon(&dst);
}
void
SIPCall::onhold()
{
if (not setState(Call::HOLD))
return;
audiortp_.saveLocalContext();
audiortp_.stop();
#ifdef SFL_VIDEO
videortp_.stop();
#endif
if (!local_sdp_)
throw SdpException("Could not find sdp session");
local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv");
local_sdp_->removeAttributeFromLocalAudioMedia("sendonly");
local_sdp_->addAttributeToLocalAudioMedia("sendonly");
#ifdef SFL_VIDEO
local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv");
local_sdp_->removeAttributeFromLocalVideoMedia("inactive");
local_sdp_->addAttributeToLocalVideoMedia("inactive");
#endif
if (SIPSessionReinvite(this) != PJ_SUCCESS)
WARN("Reinvite failed");
}
void
SIPCall::offhold()
{
SIPAccount *account = Manager::instance().getSipAccount(getAccountId());
try {
if (account and account->isStunEnabled())
internalOffHold([&] { updateSDPFromSTUN(*this, *account, *SIPVoIPLink::instance().sipTransport); });
else
internalOffHold([] {});
} catch (const SdpException &e) {
ERROR("%s", e.what());
throw VoipLinkException("SDP issue in offhold");
} catch (const ost::Socket::Error &e) {
throw VoipLinkException("Socket problem in offhold");
} catch (const ost::Socket *) {
throw VoipLinkException("Socket problem in offhold");
} catch (const sfl::AudioRtpFactoryException &) {
throw VoipLinkException("Socket problem in offhold");
}
}
void
SIPCall::internalOffHold(const std::function<void()> &SDPUpdateFunc)
{
if (not setState(Call::ACTIVE))
return;
if (local_sdp_ == NULL)
throw SdpException("Could not find sdp session");
std::vector<sfl::AudioCodec*> sessionMedia(local_sdp_->getSessionAudioMedia());
if (sessionMedia.empty()) {
WARN("Session media is empty");
return;
}
std::vector<sfl::AudioCodec*> audioCodecs;
for (auto & i : sessionMedia) {
if (!i)
continue;
// Create a new instance for this codec
sfl::AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(i->getPayloadType());
if (ac == NULL) {
ERROR("Could not instantiate codec %d", i->getPayloadType());
throw std::runtime_error("Could not instantiate codec");
}
audioCodecs.push_back(ac);
}
if (audioCodecs.empty()) {
throw std::runtime_error("Could not instantiate any codecs");
}
audiortp_.initConfig();
audiortp_.initSession();
// Invoke closure
SDPUpdateFunc();
audiortp_.restoreLocalContext();
audiortp_.initLocalCryptoInfoOnOffHold();
audiortp_.start(audioCodecs);
local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv");
local_sdp_->removeAttributeFromLocalAudioMedia("sendonly");
local_sdp_->addAttributeToLocalAudioMedia("sendrecv");
#ifdef SFL_VIDEO
local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv");
local_sdp_->removeAttributeFromLocalVideoMedia("sendonly");
local_sdp_->removeAttributeFromLocalVideoMedia("inactive");
local_sdp_->addAttributeToLocalVideoMedia("sendrecv");
#endif
if (SIPSessionReinvite(this) != PJ_SUCCESS) {
WARN("Reinvite failed, resuming hold");
onhold();
}
}
......@@ -110,9 +110,6 @@ class SIPCall : public Call {
void setContactHeader(pj_str_t *contact);
void onhold();
void offhold(const std::function<void()> &SDPUpdateFunc);
VoIPLink* getVoIPLink() const;
void answer();
......@@ -125,6 +122,10 @@ class SIPCall : public Call {
bool attendedTransfer(const std::string& to);
void onhold();
void offhold();
private:
// override of Call::createHistoryEntry
......@@ -138,6 +139,8 @@ class SIPCall : public Call {
*/
bool transferCommon(pj_str_t *dst);
void internalOffHold(const std::function<void()> &SDPUpdateFunc);
/**
* Audio Rtp Session factory
*/
......
......@@ -1048,43 +1048,6 @@ SIPVoIPLink::peerHungup(const std::string& id)
removeSipCall(id);
}
void
SIPVoIPLink::onhold(const std::string& id)
{
auto call = getSipCall(id);
if (!call)
return;
call->onhold();
}
void
SIPVoIPLink::offhold(const std::string& id)
{
auto call = getSipCall(id);
if (!call)
return;
SIPAccount *account = Manager::instance().getSipAccount(call->getAccountId());
try {
if (account and account->isStunEnabled())
call->offhold([&] { updateSDPFromSTUN(*call, *account, *sipTransport); });
else
call->offhold([] {});
} catch (const SdpException &e) {
ERROR("%s", e.what());
throw VoipLinkException("SDP issue in offhold");
} catch (const ost::Socket::Error &e) {
throw VoipLinkException("Socket problem in offhold");
} catch (const ost::Socket *) {
throw VoipLinkException("Socket problem in offhold");
} catch (const AudioRtpFactoryException &) {
throw VoipLinkException("Socket problem in offhold");
}
}
#if HAVE_INSTANT_MESSAGING
void SIPVoIPLink::sendTextMessage(const std::string &callID,
const std::string &message,
......
......@@ -165,20 +165,6 @@ class SIPVoIPLink : public VoIPLink {
*/
virtual void peerHungup(const std::string& id);
/**
* Put the call on hold
* @param id The call identifier
* @return bool True on success
*/
virtual void onhold(const std::string& id);
/**
* Put the call off hold
* @param id The call identifier
* @return bool True on success
*/
virtual void offhold(const std::string& id);
/**
* Send DTMF refering to account configuration
* @param id The call identifier
......
......@@ -99,20 +99,6 @@ class VoIPLink {
*/
virtual void peerHungup(const std::string &id) = 0;
/**
* Put a call on hold
* @param id The call identifier
* @return bool True on success
*/
virtual void onhold(const std::string &id) = 0;
/**
* Resume a call from hold state
* @param id The call identifier
* @return bool True on success
*/
virtual void offhold(const std::string &id) = 0;
/**
* Send DTMF
* @param id The call identifier
......
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