Commit 4d3c4439 authored by Guillaume Roguez's avatar Guillaume Roguez

call: states refactoring

This is a major patch about refactoring all CallState/ConnectionState
over call and subclasses.
Please read carefully this message, it's about how to use the code.

First, this patch brings a central way to store both Call class states
members: only Call::setState() (and overloaded) has to be used now.

De-facto we use it to emit to the client the StateChange call signal,
and remove this emit spread over the code. A check is also made
to not emit it if the resulting client state doesn't change for
the given CallState/ConnectionState input pair.
So using this signal elsewhere is stricly forbidden now.

Then, a code cleanup has been made to had missing setState() calls
and check the global business logic about these states changes.
I hope this cleanup is correct (almost as good as before).

State transaction logic is, as before, checked by Call::validTransition.
Please modify it if state machine needs to be changed.
Also modify Call::getStateStr() to implements daemon->client
translated state machine.

Note: no API changes in this patch. Only behavior changes.

Refs #76646

Change-Id: Iecaedc2cad89b9afdc886f978bbf5f247cbe36bb
Signed-off-by: Guillaume Roguez's avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent be51f9cd
......@@ -97,7 +97,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
/**
* Free all ressources related to this account.
* ***Current calls using this account are HUNG-UP***
* ***Current calls using this account are HANG-UP***
*/
void freeAccount();
......
......@@ -35,6 +35,7 @@
#include "manager.h"
#include "audio/ringbufferpool.h"
#include "dring/call_const.h"
#include "client/ring_signal.h"
#include "sip/sip_utils.h"
#include "ip_utils.h"
......@@ -44,6 +45,8 @@
#include "string_utils.h"
#include "enumclass_utils.h"
#include "errno.h"
namespace ring {
Call::Call(Account& account, const std::string& id, Call::CallType type)
......@@ -73,22 +76,22 @@ Call::getAccountId() const
return account_.getAccountID();
}
void
Call::setConnectionState(ConnectionState state)
{
std::lock_guard<std::mutex> lock(callMutex_);
connectionState_ = state;
}
Call::ConnectionState
Call::getConnectionState() const
{
std::lock_guard<std::mutex> lock(callMutex_);
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return connectionState_;
}
Call::CallState
Call::getState() const
{
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return callState_;
}
bool
Call::validTransition(CallState newState)
Call::validStateTransition(CallState newState)
{
switch (callState_) {
case CallState::INACTIVE:
......@@ -122,81 +125,117 @@ Call::validTransition(CallState newState)
}
bool
Call::setState(CallState state)
Call::setState(CallState call_state, ConnectionState cnx_state, signed code)
{
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 attempted call state transition from %d to %d",
callState_, state);
return false;
std::lock_guard<std::recursive_mutex> lock(callMutex_);
RING_DBG("[call:%s] state change %u/%u, cnx %u/%u, code %d", id_.c_str(),
callState_, call_state, connectionState_, cnx_state, code);
if (callState_ != call_state) {
if (not validStateTransition(call_state)) {
RING_ERR("[call:%s] invalid call state transition from %u to %u",
id_.c_str(), callState_, call_state);
return false;
}
} else if (connectionState_ == cnx_state)
return true; // no changes as no-op
// Emit client state only if changed
auto old_client_state = getStateStr();
callState_ = call_state;
connectionState_ = cnx_state;
auto new_client_state = getStateStr();
if (old_client_state != new_client_state) {
RING_DBG("[call:%s] emit client call state change %s, code %d",
id_.c_str(), new_client_state.c_str(), code);
emitSignal<DRing::CallSignal::StateChange>(id_, new_client_state, code);
}
callState_ = state;
return true;
}
Call::CallState
Call::getState() const
bool
Call::setState(CallState call_state, signed code)
{
std::lock_guard<std::mutex> lock(callMutex_);
return callState_;
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return setState(call_state, connectionState_, code);
}
bool
Call::setState(ConnectionState cnx_state, signed code)
{
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return setState(callState_, cnx_state, code);
}
std::string
Call::getStateStr() const
{
using namespace DRing::Call;
switch (getState()) {
case CallState::ACTIVE:
switch (getConnectionState()) {
case ConnectionState::PROGRESSING:
return StateEvent::CONNECTING;
case ConnectionState::RINGING:
return isIncoming() ? "INCOMING" : "RINGING";
return isIncoming() ? StateEvent::INCOMING : StateEvent::RINGING;
case ConnectionState::DISCONNECTED:
return StateEvent::HUNGUP;
case ConnectionState::CONNECTED:
default:
return "CURRENT";
return StateEvent::CURRENT;
}
case CallState::HOLD:
return "HOLD";
return StateEvent::HOLD;
case CallState::BUSY:
return "BUSY";
case CallState::INACTIVE:
return StateEvent::BUSY;
case CallState::INACTIVE:
switch (getConnectionState()) {
case ConnectionState::PROGRESSING:
return StateEvent::CONNECTING;
case ConnectionState::RINGING:
return isIncoming() ? "INCOMING" : "RINGING";
return isIncoming() ? StateEvent::INCOMING : StateEvent::RINGING;
case ConnectionState::CONNECTED:
return "CURRENT";
return StateEvent::CURRENT;
default:
return "INACTIVE";
return StateEvent::INACTIVE;
}
case CallState::MERROR:
default:
return "FAILURE";
return StateEvent::FAILURE;
}
}
IpAddr
Call::getLocalIp() const
{
std::lock_guard<std::mutex> lock(callMutex_);
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return localAddr_;
}
unsigned int
Call::getLocalAudioPort() const
{
std::lock_guard<std::mutex> lock(callMutex_);
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return localAudioPort_;
}
unsigned int
Call::getLocalVideoPort() const
{
std::lock_guard<std::mutex> lock(callMutex_);
std::lock_guard<std::recursive_mutex> lock(callMutex_);
return localVideoPort_;
}
......@@ -309,4 +348,13 @@ Call::newIceSocket(unsigned compId)
return std::unique_ptr<IceSocket> {new IceSocket(iceTransport_, compId)};
}
void
Call::peerHungup()
{
const auto state = getState();
const auto aborted = state == CallState::ACTIVE or state == CallState::HOLD;
setState(ConnectionState::DISCONNECTED,
aborted ? ECONNABORTED : ECONNREFUSED);
}
} // namespace ring
......@@ -77,12 +77,16 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
* Audio should be transmitted when ConnectionState = Connected AND
* CallState = Active.
*/
enum class ConnectionState {DISCONNECTED, TRYING, PROGRESSING, RINGING, CONNECTED, COUNT__};
enum class ConnectionState : unsigned {
DISCONNECTED, TRYING, PROGRESSING, RINGING, CONNECTED, COUNT__
};
/**
* The Call State.
*/
enum class CallState {INACTIVE, ACTIVE, HOLD, BUSY, MERROR, COUNT__};
enum class CallState : unsigned {
INACTIVE, ACTIVE, HOLD, BUSY, MERROR, COUNT__
};
virtual ~Call();
......@@ -157,24 +161,16 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
return type_ == CallType::INCOMING;
}
/**
* Set the connection state of the call (protected by mutex)
* @param state The connection state
*/
void setConnectionState(ConnectionState state);
/**
* Get the connection state of the call (protected by mutex)
* @return ConnectionState The connection state
*/
ConnectionState getConnectionState() const;
/**
* Set the state of the call (protected by mutex)
* @param state The call state
* @param call_state The call state
* @param cnx_state The call connection state
* @param code Optionnal state dependent error code (used to report more information)
* @return true if the requested state change was valid, false otherwise
*/
bool setState(CallState state);
bool setState(CallState call_state, signed code=0);
bool setState(CallState call_state, ConnectionState cnx_state, signed code=0);
bool setState(ConnectionState cnx_state, signed code=0);
/**
* Get the call state of the call (protected by mutex)
......@@ -182,6 +178,12 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
*/
CallState getState() const;
/**
* Get the connection state of the call (protected by mutex)
* @return ConnectionState The connection state
*/
ConnectionState getConnectionState() const;
std::string getStateStr() const;
void setIPToIP(bool IPToIP) {
......@@ -287,9 +289,9 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
virtual void muteMedia(const std::string& mediaType, bool isMuted) = 0;
/**
* Peer Hung up a call
* Peer has hung up a call
*/
virtual void peerHungup() = 0;
virtual void peerHungup();
/**
* Send DTMF
......@@ -341,11 +343,12 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
bool isVideoMuted_{false};
private:
bool validTransition(CallState newState);
bool validStateTransition(CallState newState);
std::string getTypeStr() const;
/** Protect every attribute that can be changed by two threads */
mutable std::mutex callMutex_ {};
mutable std::recursive_mutex callMutex_ {};
// Informations about call socket / audio
......
......@@ -45,6 +45,7 @@ constexpr static char BUSY [] = "BUSY" ;
constexpr static char FAILURE [] = "FAILURE" ;
constexpr static char HOLD [] = "HOLD" ;
constexpr static char UNHOLD [] = "UNHOLD" ;
constexpr static char INACTIVE [] = "INACTIVE" ;
}
......
......@@ -145,8 +145,7 @@ IAXAccount::newOutgoingCall(const std::string& toUrl)
iaxOutgoingInvite(call.get());
call->setConnectionState(Call::ConnectionState::PROGRESSING);
call->setState(Call::CallState::ACTIVE);
call->setState(Call::CallState::ACTIVE, Call::ConnectionState::PROGRESSING);
return call;
}
......
......@@ -150,8 +150,7 @@ IAXCall::answer()
iax_answer(session);
}
setState(Call::CallState::ACTIVE);
setConnectionState(Call::ConnectionState::CONNECTED);
setState(Call::CallState::ACTIVE, Call::ConnectionState::CONNECTED);
Manager::instance().getRingBufferPool().flushAllBuffers();
}
......@@ -210,8 +209,6 @@ IAXCall::onhold()
bool
IAXCall::offhold()
{
bool success = false;
Manager::instance().addStream(*this);
{
......@@ -219,18 +216,20 @@ IAXCall::offhold()
iax_unquelch(session);
}
if (success = setState(Call::CallState::ACTIVE))
if (setState(Call::CallState::ACTIVE)) {
Manager::instance().startAudioDriverStream();
return true;
}
return success;
return false;
}
void
IAXCall::peerHungup()
{
Manager::instance().getRingBufferPool().unBindAll(getCallId());
session = nullptr;
Call::peerHungup();
}
void
......
......@@ -216,8 +216,7 @@ IAXVoIPLink::sendAudioFromMic()
void
IAXVoIPLink::handleReject(IAXCall& call)
{
call.setConnectionState(Call::ConnectionState::CONNECTED);
call.setState(Call::CallState::MERROR);
call.setState(Call::CallState::MERROR, Call::ConnectionState::DISCONNECTED);
Manager::instance().callFailure(call);
call.removeCall();
}
......@@ -235,8 +234,7 @@ IAXVoIPLink::handleAnswerTransfer(iax_event* event, IAXCall& call)
if (call.getConnectionState() == Call::ConnectionState::CONNECTED)
return;
call.setConnectionState(Call::ConnectionState::CONNECTED);
call.setState(Call::CallState::ACTIVE);
call.setState(Call::CallState::ACTIVE, Call::ConnectionState::CONNECTED);
if (event->ies.format)
call.format = event->ies.format;
......@@ -250,8 +248,7 @@ IAXVoIPLink::handleAnswerTransfer(iax_event* event, IAXCall& call)
void
IAXVoIPLink::handleBusy(IAXCall& call)
{
call.setConnectionState(Call::ConnectionState::CONNECTED);
call.setState(Call::CallState::BUSY);
call.setState(Call::CallState::BUSY, Call::ConnectionState::CONNECTED);
Manager::instance().callBusy(call);
call.removeCall();
......@@ -269,7 +266,7 @@ IAXVoIPLink::handleMessage(iax_event* event, IAXCall& call)
void
IAXVoIPLink::handleRinging(IAXCall& call)
{
call.setConnectionState(Call::ConnectionState::RINGING);
call.setState(Call::ConnectionState::RINGING);
Manager::instance().peerRingingCall(call);
}
......@@ -413,7 +410,7 @@ void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
}
call->session = event->session;
call->setConnectionState(Call::ConnectionState::PROGRESSING);
call->setState(Call::ConnectionState::PROGRESSING);
if (event->ies.calling_number)
call->setPeerNumber(event->ies.calling_number);
......
......@@ -533,9 +533,6 @@ Manager::answerCall(const std::string& call_id)
if (audioPreference.getIsAlwaysRecording())
toggleRecordingCall(call_id);
//callStateChanged(call_id, "CURRENT");
emitSignal<DRing::CallSignal::StateChange>(call_id, "CURRENT", 0);
return result;
}
......@@ -558,9 +555,6 @@ Manager::hangupCall(const std::string& callId)
stopTone();
RING_DBG("Send call state change (HUNGUP) for id %s", callId.c_str());
emitSignal<DRing::CallSignal::StateChange>(callId, "HUNGUP", ECONNABORTED);
/* We often get here when the call was hungup before being created */
auto call = getCallFromCallID(callId);
if (not call) {
......@@ -649,8 +643,6 @@ Manager::onHoldCall(const std::string& callId)
// 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);
}
return result;
......@@ -693,8 +685,6 @@ Manager::offHoldCall(const std::string& callId)
}
if (result) {
emitSignal<DRing::CallSignal::StateChange>(callId, DRing::Call::StateEvent::UNHOLD, 0);
if (isConferenceParticipant(callId))
switchCall(getCallFromCallID(call->getConfId()));
else
......@@ -782,8 +772,6 @@ Manager::refuseCall(const std::string& id)
removeWaitingCall(id);
emitSignal<DRing::CallSignal::StateChange>(id, "HUNGUP", ECONNABORTED);
// Disconnect streams
removeStream(*call);
......@@ -1614,7 +1602,7 @@ Manager::incomingCall(Call &call, const std::string& accountId)
}
if (not hasCurrentCall()) {
call.setConnectionState(Call::ConnectionState::RINGING);
call.setState(Call::ConnectionState::RINGING);
playRingtone(accountId);
}
......@@ -1747,8 +1735,6 @@ Manager::peerAnsweredCall(Call& call)
if (audioPreference.getIsAlwaysRecording())
toggleRecordingCall(call_id);
emitSignal<DRing::CallSignal::StateChange>(call_id, "CURRENT", 0);
}
//THREAD=VoIP Call=Outgoing
......@@ -1760,8 +1746,6 @@ Manager::peerRingingCall(Call& call)
if (isCurrentCall(call))
ringback();
emitSignal<DRing::CallSignal::StateChange>(call_id, "RINGING", 0);
}
//THREAD=VoIP Call=Outgoing/Ingoing
......@@ -1769,7 +1753,7 @@ void
Manager::peerHungupCall(Call& call)
{
const auto call_id = call.getCallId();
RING_DBG("Peer hungup call %s", call_id.c_str());
RING_DBG("Peer has hungup call %s", call_id.c_str());
if (isConferenceParticipant(call_id)) {
removeParticipant(call_id);
......@@ -1780,12 +1764,6 @@ Manager::peerHungupCall(Call& call)
call.peerHungup();
const auto st = call.getState();
emitSignal<DRing::CallSignal::StateChange>(call_id, "HUNGUP",
(st == Call::CallState::ACTIVE || st == Call::CallState::HOLD) ?
ECONNABORTED : ECONNREFUSED
);
checkAudio();
removeWaitingCall(call_id);
if (not incomingCallsWaiting())
......@@ -1798,27 +1776,21 @@ Manager::peerHungupCall(Call& call)
void
Manager::callBusy(Call& call)
{
const auto call_id = call.getCallId();
emitSignal<DRing::CallSignal::StateChange>(call_id, "BUSY", 0);
if (isCurrentCall(call)) {
playATone(Tone::TONE_BUSY);
unsetCurrentCall();
}
checkAudio();
removeWaitingCall(call_id);
removeWaitingCall(call.getCallId());
}
//THREAD=VoIP
void
Manager::callFailure(Call& call, int code)
Manager::callFailure(Call& call)
{
const auto call_id = call.getCallId();
emitSignal<DRing::CallSignal::StateChange>(call_id, "FAILURE", code);
if (isCurrentCall(call)) {
playATone(Tone::TONE_BUSY);
unsetCurrentCall();
......
......@@ -709,7 +709,7 @@ class Manager {
/**
* Handle played sound when a failure occurs
*/
void callFailure(Call& call, int code=0);
void callFailure(Call& call);
/**
* Retrieve the current telephone tone
......
......@@ -175,10 +175,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl)
/* First step: wait for an initialized ICE transport for SIP channel */
if (ice->isFailed() or std::chrono::steady_clock::now() >= iceInitTimeout) {
RING_DBG("ice init failed (or timeout)");
call->setConnectionState(Call::ConnectionState::DISCONNECTED);
call->setState(Call::CallState::MERROR);
Manager::instance().callFailure(*call); // signal client
call->removeCall();
call->onFailure();
return false;
}
......@@ -191,7 +188,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl)
const auto toH = dht::InfoHash(toUri);
const auto callkey = dht::InfoHash::get("callto:" + toUri);
call->setConnectionState(Call::ConnectionState::TRYING);
call->setState(Call::ConnectionState::TRYING);
shared_this->dht_.putEncrypted(
callkey, toH,
dht::Value {
......@@ -201,11 +198,8 @@ RingAccount::newOutgoingCall(const std::string& toUrl)
[=](bool ok) { // Put complete callback
if (!ok) {
RING_WARN("Can't put ICE descriptor on DHT");
if (auto call = weak_call.lock()) {
call->setConnectionState(Call::ConnectionState::DISCONNECTED);
Manager::instance().callFailure(*call); // signal client
call->removeCall();
}
if (auto call = weak_call.lock())
call->onFailure();
} else
RING_DBG("Succesfully put ICE descriptor on DHT");
shared_this->dht_.cancelPut(callkey, callvid);
......@@ -218,11 +212,9 @@ RingAccount::newOutgoingCall(const std::string& toUrl)
if (msg.id != replyvid)
return true;
RING_WARN("ICE request replied from DHT peer %s", toH.toString().c_str());
if (auto call = weak_call.lock()) {
call->setConnectionState(Call::ConnectionState::PROGRESSING);
emitSignal<DRing::CallSignal::StateChange>(call->getCallId(), DRing::Call::StateEvent::CONNECTING, 0);
ice->start(msg.ice_data);
}
if (auto call = weak_call.lock())
call->setState(Call::ConnectionState::PROGRESSING);
ice->start(msg.ice_data);
return false;
}
);
......@@ -367,8 +359,7 @@ RingAccount::SIPStartCall(const std::shared_ptr<SIPCall>& call, IpAddr target)
return false;
}
call->setConnectionState(Call::ConnectionState::PROGRESSING);
call->setState(Call::CallState::ACTIVE);
call->setState(Call::CallState::ACTIVE, Call::ConnectionState::PROGRESSING);
return true;
}
......@@ -581,7 +572,7 @@ RingAccount::handleEvents()
};
auto tr = link_->sipTransportBroker->getTlsIceTransport(c->ice, ICE_COMP_SIP_TRANSPORT, tlsParams);
call->setTransport(tr);
call->setConnectionState(Call::ConnectionState::PROGRESSING);
call->setState(Call::ConnectionState::PROGRESSING);
if (c->call_key == dht::InfoHash()) {
RING_DBG("[call:%s] ICE succeeded : moving incomming call to pending sip call",
call->getCallId().c_str());
......@@ -600,10 +591,8 @@ RingAccount::handleEvents()
call->getCallId().c_str(), call.use_count());
if (c->call_key != dht::InfoHash())
dht_.cancelListen(c->call_key, c->listen_key.get());
call->setConnectionState(Call::ConnectionState::DISCONNECTED);
Manager::instance().callFailure(*call);
call->onFailure();
c = pendingCalls_.erase(c);
call->removeCall();
} else
++c;
}
......@@ -868,11 +857,8 @@ void RingAccount::incomingCall(dht::IceCandidates&& msg)
auto& this_ = *shared.get();
if (!ok) {
RING_WARN("Can't put ICE descriptor reply on DHT");
if (auto call = weak_call.lock()) {
call->setConnectionState(Call::ConnectionState::DISCONNECTED);
Manager::instance().callFailure(*call);
call->removeCall();
}
if (auto call = weak_call.lock())
call->onFailure();
} else
RING_DBG("Successfully put ICE descriptor reply on DHT");
this_.dht_.cancelPut(this_.callKey_, reply_vid);
......
......@@ -404,8 +404,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
return false;
}
call->setConnectionState(Call::ConnectionState::PROGRESSING);
call->setState(Call::CallState::ACTIVE);
call->setState(Call::CallState::ACTIVE, Call::ConnectionState::PROGRESSING);
return true;
}
......
......@@ -210,9 +210,7 @@ SIPCall::setTransport(const std::shared_ptr<SipTransport>& t)
// end the call if the SIP transport is shut down
if (not SipTransport::isAlive(t, state) and this_->getConnectionState() != ConnectionState::DISCONNECTED) {
RING_WARN("Ending call because underlying SIP transport was closed");
this_->setConnectionState(ConnectionState::DISCONNECTED);
Manager::instance().callFailure(*this_, ECONNRESET);
this_->removeCall();
this_->onFailure(ECONNRESET);
}
} else // should not happen
t->removeStateListener(list_id);
......@@ -335,8 +333,7 @@ void SIPCall::answer()
throw std::runtime_error("Could not send invite request answer (200 OK)");
}
setConnectionState(ConnectionState::CONNECTED);
setState(CallState::ACTIVE);
setState(CallState::ACTIVE, ConnectionState::CONNECTED);
}
static void
......@@ -389,6 +386,7 @@ SIPCall::hangup(int reason)
sendEndSessionMsg(inv.get(), status, &contactStr);
inv.reset();
setState(Call::ConnectionState::DISCONNECTED, reason);
removeCall();
}
......@@ -406,6 +404,7 @@ SIPCall::refuse()
sendEndSessionMsg(inv.get(), PJSIP_SC_DECLINE, &contactStr);
inv.reset();
setState(Call::ConnectionState::DISCONNECTED, ECONNABORTED);
removeCall();
}
......@@ -659,19 +658,25 @@ SIPCall::peerHungup()
if (not inv)
throw VoipLinkException("No invite session for this call");
// User hangup current call. Notify peer
pjsip_tx_data *tdata = NULL;
pj_status_t ret;
ret = pjsip_inv_end_session(inv.get(), 404, nullptr, &tdata);
if (ret == PJ_SUCCESS and tdata) {
ret = pjsip_inv_send_msg(inv.get(), tdata);
if (ret == PJ_SUCCESS) {
// Make sure user data is nullptr in callbacks
inv->mod_data[getSIPVoIPLink()->getModId()] = nullptr;
goto terminate;
}
}
if (pjsip_inv_end_session(inv.get(), 404, NULL, &tdata) != PJ_SUCCESS || !tdata)
return;
// error case
inv.reset();
sip_utils::sip_printerror(ret);
if (auto ret = pjsip_inv_send_msg(inv.get(), tdata) == PJ_SUCCESS) {
// Make sure user data is NULL in callbacks
inv->mod_data[getSIPVoIPLink()->getModId()] = NULL;
} else {
inv.reset();
sip_utils::sip_printerror(ret);
}
terminate:
Call::peerHungup();
}
void
......@@ -699,9 +704,10 @@ void SIPCall::sendTextMessage(const std::map<std::string, std::string>& messages
#endif // HAVE_INSTANT_MESSAGING
void
SIPCall::onServerFailure(int code)
SIPCall::onFailure(signed cause)
{
Manager::instance().callFailure(*this, code);
setState(CallState::MERROR, ConnectionState::DISCONNECTED, cause);
Manager::instance().callFailure(*this);
removeCall();
}
......@@ -717,8 +723,7 @@ void
SIPCall::onAnswered()
{
if (getConnectionState() != ConnectionState::CONNECTED) {
setConnectionState(ConnectionState::CONNECTED);
setState(CallState::ACTIVE);
setState(CallState::ACTIVE, ConnectionState::CONNECTED);
Manager::instance().peerAnsweredCall(*this);
}
}
......@@ -726,7 +731,7 @@ SIPCall::onAnswered()
void
SIPCall::onPeerRinging()
{
setConnectionState(ConnectionState::RINGING);
setState(ConnectionState::RINGING);