Commit af242515 authored by Guillaume Roguez's avatar Guillaume Roguez

daemon: implement VoIP link stack auto registering

Less SIP/IAX dependencies! \o/

Refs #52476

Change-Id: I8dfc825df094db47bdb1270b551e2554eeda575e
parent ed4bf2fc
......@@ -91,7 +91,6 @@ libsflphone_la_SOURCES = conference.cpp \
conference.h \
account factory.h \
call factory.h \
voiplink.h \
preferences.h \
managerimpl.h \
manager.h \
......
......@@ -44,7 +44,6 @@
#include "logger.h"
#include "manager.h"
#include "voiplink.h"
#include "client/configurationmanager.h"
......
......@@ -44,10 +44,16 @@
#include <memory>
#include <map>
#include <set>
#include <stdexcept>
class VoIPLink;
class Call;
class VoipLinkException : public std::runtime_error {
public:
VoipLinkException(const std::string &str = "") :
std::runtime_error("VoipLinkException occured: " + str) {}
};
/**
* @file account.h
* @brief Interface to protocol account (SIPAccount, IAXAccount)
......@@ -95,12 +101,6 @@ class Account : public Serializable {
*/
virtual bool isIP2IP() const { return false; }
/**
* Get the voiplink pointer
* @return VoIPLink* the pointer or 0
*/
virtual VoIPLink* getVoIPLink() = 0;
/**
* Register the underlying VoIPLink. Launch the event listener.
* This should update the getRegistrationState() return value.
......
......@@ -235,8 +235,6 @@ class Call : public Recordable {
virtual bool toggleRecording();
virtual VoIPLink* getVoIPLink() const = 0;
/**
* Answer the call
*/
......
......@@ -278,14 +278,6 @@ sfl::AudioZrtpSession *
CallManager::getAudioZrtpSession(const std::string& callID)
{
// TODO: remove SIP dependency
// IP2IP profile is associated with IP2IP profile anyway
const auto& ip2ipAccount = Manager::instance().getIP2IPAccount();
auto link = static_cast<SIPVoIPLink *>(ip2ipAccount->getVoIPLink());
if (!link)
throw CallManagerException("Failed to get sip link");
const auto call = Manager::instance().callFactory.getCall<SIPCall>(callID);
if (!call)
throw CallManagerException("Call id " + callID + " is not valid");
......
......@@ -49,7 +49,7 @@
constexpr const char * const IAXAccount::ACCOUNT_TYPE;
IAXAccount::IAXAccount(const std::string& accountID)
: Account(accountID), password_(), link_(*this)
: Account(accountID), password_(), link_(new IAXVoIPLink(*this))
{}
void IAXAccount::serialize(Conf::YamlEmitter &emitter)
......@@ -142,7 +142,7 @@ std::map<std::string, std::string> IAXAccount::getAccountDetails() const
void IAXAccount::registerVoIPLink()
{
try {
link_.init();
link_->init();
sendRegister();
} catch (const VoipLinkException &e) {
ERROR("IAXAccount: %s", e.what());
......@@ -154,7 +154,7 @@ IAXAccount::unregisterVoIPLink(std::function<void(bool)> cb)
{
try {
sendUnregister();
link_.terminate();
link_->terminate();
} catch (const VoipLinkException &e) {
ERROR("IAXAccount: %s", e.what());
}
......
......@@ -96,10 +96,6 @@ class IAXAccount : public Account {
void checkRegister();
VoIPLink* getVoIPLink() {
return &link_;
}
/**
* Implementation of Account::newOutgoingCall()
* Note: keep declaration before newOutgoingCall template.
......@@ -146,7 +142,7 @@ class IAXAccount : public Account {
// Account login information: password
std::string password_;
IAXVoIPLink link_;
std::unique_ptr<IAXVoIPLink> link_;
/** Timestamp of when we should refresh the registration up with
* the registrar. Values can be: EPOCH timestamp, 0 if we want no registration, 1
......
......@@ -71,8 +71,7 @@ codecToASTFormat(int c)
IAXCall::IAXCall(IAXAccount& account, const std::string& id, Call::CallType type)
: Call(account, id, type),
format(0),
session(NULL),
link_(static_cast<IAXVoIPLink*>(account.getVoIPLink()))
session(NULL)
{}
int IAXCall::getSupportedFormat(const std::string &accountID) const
......@@ -133,10 +132,6 @@ int IAXCall::getAudioCodec() const
}
}
VoIPLink*
IAXCall::getVoIPLink() const
{ return link_; }
void
IAXCall::answer()
{
......
......@@ -39,8 +39,6 @@
#include "call.h"
#include "noncopyable.h"
class VoIPLink;
class IAXVoIPLink;
class IAXAccount;
/**
......@@ -88,8 +86,6 @@ class IAXCall : public Call
int format;
iax_session* session;
VoIPLink* getVoIPLink() const;
void answer();
void hangup(int reason);
......@@ -115,8 +111,6 @@ class IAXCall : public Call
private:
NON_COPYABLE(IAXCall);
IAXVoIPLink* link_;
};
#endif
......@@ -2,7 +2,7 @@
* Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
* Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author : Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
* Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -35,16 +35,17 @@
#include <cmath>
#include <algorithm>
#include "manager.h"
#include "iaxcall.h"
#include "iaxaccount.h"
#include "logger.h"
#include "manager.h"
#include "hooks/urlhook.h"
#include "audio/audiolayer.h"
#include "audio/resampler.h"
#include "array_size.h"
#include "map_utils.h"
#include "call_factory.h"
#include "sfl_types.h"
std::mutex IAXVoIPLink::mutexIAX = {};
......@@ -72,7 +73,7 @@ IAXVoIPLink::init()
for (int port = IAX_DEFAULT_PORTNO, nbTry = 0; nbTry < 3 ; port = rand() % 64000 + 1024, nbTry++) {
if (iax_init(port) >= 0) {
handlingEvents_ = true;
Manager::instance().registerEventHandler((uintptr_t)this, std::bind(&IAXVoIPLink::handleEvents, this));
initDone_ = true;
break;
}
......@@ -85,7 +86,7 @@ IAXVoIPLink::terminate()
if (!initDone_)
return;
handlingEvents_ = false;
Manager::instance().unregisterEventHandler((uintptr_t)this);
for (const auto& call : Manager::instance().callFactory.getAllCalls<IAXCall>()) {
std::lock_guard<std::mutex> lock(mutexIAX);
......@@ -106,7 +107,7 @@ iaxGetCallFromSession(iax_session* session)
return nullptr;
}
bool
void
IAXVoIPLink::handleEvents()
{
iax_event *event = NULL;
......@@ -146,10 +147,6 @@ IAXVoIPLink::handleEvents()
account_.checkRegister();
sendAudioFromMic();
// thread wait 3 millisecond
usleep(3000);
return handlingEvents_;
}
void
......
......@@ -38,7 +38,6 @@
#endif
#include "account.h"
#include "voiplink.h"
#include "audio/audiobuffer.h"
#include "audio/codecs/audiocodec.h" // for RAW_BUFFER_SIZE
#include "sfl_types.h"
......@@ -60,22 +59,20 @@ class AudioLayer;
* and contains IAX Call related functions
*/
class IAXVoIPLink : public VoIPLink {
class IAXVoIPLink {
public:
IAXVoIPLink(IAXAccount& account);
~IAXVoIPLink();
/**
* Listen to events sent by the call manager ( asterisk, etc .. )
*/
bool handleEvents();
void handleEvents();
/**
* Init the voip link
*/
virtual void init();
void init();
/**
* Terminate a voip link by clearing the call list
......@@ -86,7 +83,7 @@ class IAXVoIPLink : public VoIPLink {
* Cancel a call
* @param id The ID of the call
*/
virtual void cancel(const std::string& /*id*/) {}
void cancel(const std::string& /*id*/) {}
/** Mutex for iax_ calls, since we're the only one dealing with the incorporated
* iax_stuff inside this class. */
......
......@@ -45,20 +45,12 @@
#include "global.h"
#include "fileutils.h"
#include "map_utils.h"
#include "voiplink.h"
#include "account.h"
#include "call_factory.h"
// FIXME: remove these dependencies
#include "sip/sipvoiplink.h"
#include "sip/sip_utils.h"
#if HAVE_IAX
#include "iax/iaxvoiplink.h"
#include "iax/iaxaccount.h"
#endif
#include "im/instant_messaging.h"
#include "numbercleaner.h"
......@@ -140,7 +132,6 @@ ManagerImpl::ManagerImpl() :
waitingCalls_(), waitingCallsMutex_(), path_(),
mainBuffer_(), callFactory(), conferenceMap_(), history_(),
finished_(false), accountFactory_()
{
// initialize random generator for call id
srand(time(nullptr));
......@@ -287,7 +278,6 @@ ManagerImpl::finish()
// Disconnect accounts, close link stacks and free allocated ressources
unregisterAccounts();
accountFactory_.clear();
SIPVoIPLink::destroy();
{
std::lock_guard<std::mutex> lock(audioLayerMutex_);
......@@ -1310,18 +1300,26 @@ ManagerImpl::removeStream(const std::string& call_id)
getMainBuffer().unBindAll(call_id);
}
void
ManagerImpl::registerEventHandler(uintptr_t handlerId, EventHandler handler)
{
eventHandlerMap_.insert(std::make_pair(handlerId, handler));
}
void
ManagerImpl::unregisterEventHandler(uintptr_t handlerId)
{
eventHandlerMap_.erase(handlerId);
}
// Must be invoked periodically by a timer from the main event loop
void ManagerImpl::pollEvents()
{
if (finished_)
return;
SIPVoIPLink::instance().handleEvents();
#if HAVE_IAX
for (auto account : accountFactory_.getAllAccounts<IAXAccount>())
account->getVoIPLink()->handleEvents();
#endif
for (const auto& it : eventHandlerMap_)
it.second();
}
//THREAD=Main
......
......@@ -74,7 +74,6 @@ class AudioFile;
class AudioLayer;
class History;
class TelephoneTone;
class VoIPLink;
/** To send multiple string */
typedef std::list<std::string> TokenList;
......@@ -977,9 +976,26 @@ class ManagerImpl {
CallFactory callFactory;
using EventHandler = std::function<void()>;
/**
* Install an event handler called periodically by pollEvents().
* @param handlerId an unique identifier for the handler.
* @param handler the event handler function.
*/
void registerEventHandler(uintptr_t handlerId, EventHandler handler);
/**
* Remove a previously registered event handler.
* @param handlerId id of handler to remove.
*/
void unregisterEventHandler(uintptr_t handlerId);
private:
NON_COPYABLE(ManagerImpl);
std::map<uintptr_t, EventHandler> eventHandlerMap_{};
/**
* Test if call is a valid call, i.e. have been created and stored in
* call-account map
......@@ -1017,4 +1033,5 @@ class ManagerImpl {
void loadAccount(const Conf::YamlNode *item, int &errorCount,
const std::string &accountOrder);
};
#endif // MANAGER_IMPL_H_
......@@ -34,6 +34,7 @@
#include <cstddef> // for size_t
#include <stdint.h>
#include <type_traits>
#include <memory>
typedef int16_t SFLAudioSample;
#define SFL_DATA_FORMAT_MAX SHRT_MAX
......@@ -47,4 +48,25 @@ static const size_t SIZEBUF = 32000; /** About 1s of buffering at 48kHz */
template <class T, class U>
using enable_if_base_of = typename std::enable_if<std::is_base_of<T, U>::value, T>::type;
/**
* Return a shared pointer on an auto-generated global instance of class T.
* This instance is created only at usage and destroyed when not,
* as we keep only a weak reference on it.
* But when created it's always the same object until all holders release their sharing.
*/
template <class T>
std::shared_ptr<T>
getGlobalInstance()
{
static std::weak_ptr<T> wlink;
if (wlink.expired()) {
auto link = std::make_shared<T>();
wlink = link;
return link;
}
return wlink.lock();
}
#endif // SFL_TYPES_H_
......@@ -384,10 +384,8 @@ bool PresSubClient::isTermReason(const std::string &reason)
void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
{
SIPAccount * acc = pres_->getAccount();
if (timer_.id) {
pjsip_endpt_cancel_timer(((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint(), &timer_);
pjsip_endpt_cancel_timer(getSIPVoIPLink()->getEndpoint(), &timer_);
timer_.id = PJ_FALSE;
}
......@@ -401,7 +399,7 @@ void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
delay.msec = msec;
pj_time_val_normalize(&delay);
if (pjsip_endpt_schedule_timer(((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
if (pjsip_endpt_schedule_timer(getSIPVoIPLink()->getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
timer_.id = PJ_TRUE;
}
}
......
......@@ -126,7 +126,7 @@ PresSubServer::pres_on_rx_subscribe_request(pjsip_rx_data *rdata)
return PJ_FALSE;
}
pjsip_endpoint *endpt = ((SIPVoIPLink*) sipaccount->getVoIPLink())->getEndpoint();
pjsip_endpoint *endpt = getSIPVoIPLink()->getEndpoint();
SIPPresence * pres = sipaccount->getPresence();
pres->lock();
......
......@@ -144,7 +144,7 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
, keepAliveEnabled_(false)
, keepAliveTimer_()
, keepAliveTimerActive_(false)
, link_(SIPVoIPLink::instance())
, link_(getSIPVoIPLink())
, receivedParameter_("")
, rPort_(-1)
, via_addr_()
......@@ -365,7 +365,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
return false;
}
call->inv->mod_data[link_.getModId()] = call.get();
call->inv->mod_data[link_->getModId()] = call.get();
pjsip_tx_data *tdata;
......@@ -1196,7 +1196,7 @@ void SIPAccount::startKeepAliveTimer()
keepAliveTimerActive_ = true;
link_.registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
}
void SIPAccount::stopKeepAliveTimer()
......@@ -1204,7 +1204,7 @@ void SIPAccount::stopKeepAliveTimer()
if (keepAliveTimerActive_) {
DEBUG("Stop keep alive timer %d for account %s", keepAliveTimer_.id, getAccountID().c_str());
keepAliveTimerActive_ = false;
link_.cancelKeepAliveTimer(keepAliveTimer_);
link_->cancelKeepAliveTimer(keepAliveTimer_);
}
}
......@@ -1217,7 +1217,7 @@ SIPAccount::sendRegister()
}
try {
link_.sipTransport->createSipTransport(*this);
link_->sipTransport->createSipTransport(*this);
} catch (const std::runtime_error &e) {
ERROR("%s", e.what());
throw VoipLinkException("Could not create or acquire SIP transport");
......@@ -1227,7 +1227,7 @@ SIPAccount::sendRegister()
setRegistrationState(RegistrationState::TRYING);
pjsip_regc *regc = nullptr;
if (pjsip_regc_create(link_.getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
if (pjsip_regc_create(link_->getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
throw VoipLinkException("UserAgent: Unable to create regc structure.");
std::string srvUri(getServerUri());
......@@ -1265,7 +1265,7 @@ SIPAccount::sendRegister()
}
if (hasServiceRoute())
pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
pjsip_regc_set_credentials(regc, getCredentialCount(), getCredInfo());
......@@ -1275,7 +1275,7 @@ SIPAccount::sendRegister()
pj_str_t pJuseragent = pj_str((char*) useragent.c_str());
const pj_str_t STR_USER_AGENT = CONST_PJ_STR("User-Agent");
pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_.getPool(), &STR_USER_AGENT, &pJuseragent);
pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_->getPool(), &STR_USER_AGENT, &pJuseragent);
pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
pjsip_regc_add_headers(regc, &hdr_list);
pjsip_tx_data *tdata;
......@@ -1294,7 +1294,7 @@ SIPAccount::sendRegister()
}
setRegistrationInfo(regc);
link_.sipTransport->cleanupTransports();
link_->sipTransport->cleanupTransports();
}
void
......@@ -1345,12 +1345,12 @@ SIPAccount::onRegister(pjsip_regc_cbparam *param)
*/
// update_rfc5626_status(acc, param->rdata);
if (checkNATAddress(param, SIPVoIPLink::instance().getPool()))
if (checkNATAddress(param, link_->getPool()))
WARN("Contact overwritten");
/* TODO Check and update Service-Route header */
if (hasServiceRoute())
pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), SIPVoIPLink::instance().getPool()));
pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
// start the periodic registration request based on Expire header
// account determines itself if a keep alive is required
......@@ -1371,13 +1371,13 @@ SIPAccount::onRegister(pjsip_regc_cbparam *param)
case PJSIP_SC_BAD_GATEWAY:
case PJSIP_SC_SERVICE_UNAVAILABLE:
case PJSIP_SC_SERVER_TIMEOUT:
scheduleReregistration(link_.getEndpoint());
scheduleReregistration(link_->getEndpoint());
break;
default:
/* Global failure */
if (PJSIP_IS_STATUS_IN_CLASS(param->code, 600))
scheduleReregistration(link_.getEndpoint());
scheduleReregistration(link_->getEndpoint());
}
const pj_str_t *description = pjsip_get_status_text(param->code);
......@@ -1426,9 +1426,9 @@ SIPAccount::sendUnregister(std::function<void(bool)> released_cb)
// remove the transport from the account
auto transport = getTransport();
setTransport();
link_.sipTransport->cleanupTransports();
link_->sipTransport->cleanupTransports();
if (released_cb)
link_.sipTransport->waitForReleased(transport, released_cb);
link_->sipTransport->waitForReleased(transport, released_cb);
}
#if HAVE_TLS
......@@ -1681,14 +1681,14 @@ SIPAccount::getContactHeader()
std::string address;
pj_uint16_t port;
link_.sipTransport->findLocalAddressFromTransport(transport_, transportType, hostname_, address, port);
link_->sipTransport->findLocalAddressFromTransport(transport_, transportType, hostname_, address, port);
if (not publishedSameasLocal_) {
address = publishedIpAddress_;
port = publishedPort_;
DEBUG("Using published address %s and port %d", address.c_str(), port);
} else if (stunEnabled_) {
link_.sipTransport->findLocalAddressFromSTUN(transport_, &stunServerName_, stunPort_, address, port);
link_->sipTransport->findLocalAddressFromSTUN(transport_, &stunServerName_, stunPort_, address, port);
setPublishedAddress(address);
publishedPort_ = port;
usePublishedAddressPortInVIA();
......@@ -1739,7 +1739,7 @@ SIPAccount::getHostPortFromSTUN(pj_pool_t *pool)
{
std::string addr;
pj_uint16_t port;
link_.sipTransport->findLocalAddressFromSTUN(transport_, &stunServerName_, stunPort_, addr, port);
link_->sipTransport->findLocalAddressFromSTUN(transport_, &stunServerName_, stunPort_, addr, port);
pjsip_host_port result;
pj_strdup2(pool, &result.host, addr.c_str());
result.host.slen = addr.length();
......@@ -1991,11 +1991,6 @@ void SIPAccount::setTlsSettings(const std::map<std::string, std::string>& detail
set_opt(details, CONFIG_TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeoutSec_);
}
VoIPLink* SIPAccount::getVoIPLink()
{
return &link_;
}
bool SIPAccount::isIP2IP() const
{
return accountID_ == IP2IP_PROFILE;
......
......@@ -116,7 +116,6 @@ class SIPVoIPLink;
class SIPPresence;
class SIPCall;
/**
* @file sipaccount.h
* @brief A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
......@@ -144,8 +143,6 @@ class SIPAccount : public Account {
return ACCOUNT_TYPE;
}
VoIPLink* getVoIPLink();
pjsip_host_port getHostPortFromSTUN(pj_pool_t *pool);
std::string getUserAgentName() const;
......@@ -907,7 +904,7 @@ class SIPAccount : public Account {
/**
* Voice over IP Link contains a listener thread and calls
*/
SIPVoIPLink& link_;
std::shared_ptr<SIPVoIPLink> link_;
/**
* Optional: "received" parameter from VIA header
......
......@@ -34,6 +34,7 @@
#include "call_factory.h"
#include "sipcall.h"
#include "sipvoiplink.h"
#include "sip_utils.h"
#include "logger.h" // for _debug
#include "sdp.h"
......@@ -56,7 +57,6 @@ getSettings()
return videoman->getSettings(videoman->getDefaultDevice());
}
#endif
#include "sipvoiplink.h"
static const int INITIAL_SIZE = 16384;
static const int INCREMENT_SIZE = INITIAL_SIZE;
......@@ -105,7 +105,7 @@ SIPCall::SIPCall(SIPAccount& account, const std::string& id,
// The ID is used to associate video streams to calls
, videortp_(id, getSettings())
#endif
, pool_(pj_pool_create(&SIPVoIPLink::instance().getCachingPool()->factory,
, pool_(pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory,
id.c_str(), INITIAL_SIZE, INCREMENT_SIZE, NULL))
, local_sdp_(new Sdp(pool_))
, contactBuffer_()
......@@ -114,13 +114,13 @@ SIPCall::SIPCall(SIPAccount& account, const std::string& id,
SIPCall::~SIPCall()
{
const auto mod_ua_id = SIPVoIPLink::instance().getModId();
const auto mod_ua_id = getSIPVoIPLink()->getModId();
// prevent this from getting accessed in callbacks
// WARN: this is not thread-safe!
if (inv->mod_data[mod_ua_id]) {
WARN("Call was not properly removed from invite callbacks");
// WARN: this assignation is not thread-safe!
inv->mod_data[mod_ua_id] = nullptr;
}
......@@ -206,10 +206,6 @@ SIPCall::SIPSessionReinvite()
return !PJ_SUCCESS;
}
VoIPLink*
SIPCall::getVoIPLink() const
{ return &SIPVoIPLink::instance(); }
void
SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
{
......@@ -236,7 +232,7 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
if (tdata->msg->body == NULL)
pjsip_tx_data_dec_ref(tdata);
else
pjsip_dlg_send_request(inv->dlg, tdata, SIPVoIPLink::instance().getModId(), NULL);
pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
}
void
......@@ -246,7 +242,7 @@ SIPCall::updateSDPFromSTUN()
std::vector<long> socketDescriptors(getAudioRtp().getSocketDescriptors());
try {
std::vector<pj_sockaddr> stunPorts(SIPVoIPLink::instance().sipTransport->getSTUNAddresses(account, socketDescriptors));
std::vector<pj_sockaddr> stunPorts(getSIPVoIPLink()->sipTransport->getSTUNAddresses(account, socketDescriptors));
// FIXME: get video sockets
//stunPorts.resize(4);
......@@ -265,11 +261,9 @@ void SIPCall::answer()
auto& account = getSIPAccount();
if (!inv->neg) {
SIPVoIPLink& siplink = SIPVoIPLink::instance();
WARN("Negotiator is NULL, we've received an INVITE without an SDP");
pjmedia_sdp_session *dummy = 0;
siplink.createSDPOffer(inv, &dummy);
getSIPVoIPLink()->createSDPOffer(inv, &dummy);
if (account.isStunEnabled())
updateSDPFromSTUN();
......@@ -339,10 +333,8 @@ SIPCall::hangup(int reason)
if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS)
return;
auto& siplink = SIPVoIPLink::instance();
// Make sure user data is NULL in callbacks
inv->mod_data[siplink.getModId()] = NULL;
inv->mod_data[getSIPVoIPLink()->getModId()] = NULL;
// Stop all RTP streams
stopRtpIfCurrent();
......@@ -366,10 +358,8 @@ SIPCall::refuse()
if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS)
return;
auto& siplink = SIPVoIPLink::instance();
// Make sure the pointer is NULL in callbacks
inv->mod_data[siplink.getModId()] = NULL;
inv->mod_data[getSIPVoIPLink()->getModId()] = NULL;
removeCall();
}
......@@ -377,7 +367,7 @@ SIPCall::refuse()
static void
transfer_client_cb(pjsip_evsub *sub, pjsip_event *event)
{
auto mod_ua_id = SIPVoIPLink::instance().getModId();
auto mod_ua_id = getSIPVoIPLink()->getModId();
switch (pjsip_evsub_get_state(sub)) {
case PJSIP_EVSUB_STATE_ACCEPTED:
......@@ -465,14 +455,12 @@ SIPCall::transferCommon(pj_str_t *dst)