Commit ff28ec7a authored by Guillaume Roguez's avatar Guillaume Roguez Committed by Tristan Matthews

daemon: move call creation into Account class

This patch cleanup the design by moving call creation responsability
to the Account class.

To do that, an account in now strongly linked to a call.
This moves a lot of call managing code from *voiplink classes
into account/call classes.

Refs #51555

Change-Id: I532e40048c3b0cb8a405f48d7e2edbdf38d65cb9
parent ba3a05d9
......@@ -40,9 +40,11 @@
#include <functional>
#include <string>
#include <vector>
#include <memory>
class Account;
class VoIPLink;
class Call;
/** Define a type for a AccountMap container */
typedef std::map<std::string, Account*> AccountMap;
......@@ -100,6 +102,15 @@ class Account : public Serializable {
*/
virtual void unregisterVoIPLink(std::function<void(bool)> cb = std::function<void(bool)>()) = 0;
/**
* Create a new outgoing call
* @param id The ID of the call
* @param toUrl The address to call
* @return Call* A pointer on the call
*/
virtual std::shared_ptr<Call> newOutgoingCall(const std::string& id,
const std::string& toUrl) = 0;
/**
* Tell if the account is enable or not.
* @return true if enabled
......
......@@ -33,7 +33,7 @@
#include "audio/mainbuffer.h"
#include "history/historyitem.h"
Call::Call(const std::string& id, Call::CallType type, const std::string &accountID)
Call::Call(const std::string& id, Call::CallType type, Account& account)
: callMutex_()
, localAddr_()
, localAudioPort_(0)
......@@ -41,7 +41,7 @@ Call::Call(const std::string& id, Call::CallType type, const std::string &accoun
, id_(id)
, confID_()
, type_(type)
, accountID_(accountID)
, account_(account)
, connectionState_(Call::DISCONNECTED)
, callState_(Call::INACTIVE)
, isIPToIP_(false)
......@@ -56,6 +56,11 @@ Call::Call(const std::string& id, Call::CallType type, const std::string &accoun
Call::~Call()
{}
std::string Call::getAccountId() const
{
return account_.getAccountID();
}
void
Call::setConnectionState(ConnectionState state)
{
......@@ -231,7 +236,7 @@ std::map<std::string, std::string> Call::createHistoryEntry() const
using sfl::HistoryItem;
std::map<std::string, std::string> result;
result[HistoryItem::ACCOUNT_ID_KEY] = accountID_;
result[HistoryItem::ACCOUNT_ID_KEY] = getAccountId();
result[HistoryItem::CONFID_KEY] = confID_;
result[HistoryItem::CALLID_KEY] = id_;
result[HistoryItem::DISPLAY_NAME_KEY] = displayName_;
......@@ -268,7 +273,7 @@ Call::getDetails()
details["CALL_STATE"] = getStateStr();
details["CONF_ID"] = confID_;
details["TIMESTAMP_START"] = timestamp_to_string(timestamp_start_);
details["ACCOUNTID"] = accountID_;
details["ACCOUNTID"] = getAccountId();
return details;
}
......
......@@ -42,6 +42,7 @@
#include <sstream>
class VoIPLink;
class Account;
/*
* @file call.h
......@@ -78,7 +79,7 @@ class Call : public Recordable {
* @param id Unique identifier of the call
* @param type set definitely this call as incoming/outgoing
*/
Call(const std::string& id, Call::CallType type, const std::string &accountID);
Call(const std::string& id, Call::CallType type, Account& account);
virtual ~Call();
/**
......@@ -101,9 +102,8 @@ class Call : public Recordable {
confID_ = id;
}
std::string getAccountId() const {
return accountID_;
}
Account& getAccount() const { return account_; }
std::string getAccountId() const;
CallType getCallType() const {
return type_;
......@@ -328,7 +328,7 @@ class Call : public Recordable {
CallType type_;
/** Associate account ID */
std::string accountID_;
Account& account_;
/** Disconnected/Progressing/Trying/Ringing/Connected */
ConnectionState connectionState_;
......
......@@ -38,6 +38,7 @@
#include "iaxaccount.h"
#include "account_schema.h"
#include "iaxvoiplink.h"
#include "iaxcall.h"
#include "logger.h"
#include "manager.h"
#include "config/yamlnode.h"
......@@ -46,7 +47,7 @@
const char * const IAXAccount::ACCOUNT_TYPE = "IAX";
IAXAccount::IAXAccount(const std::string& accountID)
: Account(accountID), password_(), link_(accountID)
: Account(accountID), password_(), link_(*this)
{}
void IAXAccount::serialize(Conf::YamlEmitter &emitter)
......@@ -172,3 +173,40 @@ VoIPLink* IAXAccount::getVoIPLink()
{
return &link_;
}
std::shared_ptr<Call>
IAXAccount::newOutgoingCall(const std::string& id, const std::string& toUrl)
{
std::shared_ptr<IAXCall> call(new IAXCall(id, Call::OUTGOING, *this, &link_));
call->setPeerNumber(toUrl);
call->initRecFilename(toUrl);
iaxOutgoingInvite(call.get());
call->setConnectionState(Call::PROGRESSING);
call->setState(Call::ACTIVE);
IAXVoIPLink::addIaxCall(call);
return call;
}
void
IAXAccount::iaxOutgoingInvite(IAXCall* call)
{
std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX);
call->session = iax_session_new();
std::string username(getUsername());
std::string strNum(username + ":" + getPassword() + "@" + getHostname() + "/" + call->getPeerNumber());
/** @todo Make preference dynamic, and configurable */
const auto accountID = getAccountID();
int audio_format_preferred = call->getFirstMatchingFormat(call->getSupportedFormat(accountID), accountID);
int audio_format_capability = call->getSupportedFormat(accountID);
iax_call(call->session, username.c_str(), username.c_str(), strNum.c_str(),
NULL, 0, audio_format_preferred, audio_format_capability);
}
......@@ -42,6 +42,15 @@ class IAXAccount : public Account {
public:
IAXAccount(const std::string& accountID);
/**
* Create a new outgoing call
* @param id The ID of the call
* @param toUrl The address to call
* @return Call* A pointer on the call
*/
std::shared_ptr<Call> newOutgoingCall(const std::string& id,
const std::string& toUrl);
virtual void serialize(Conf::YamlEmitter &emitter);
virtual void unserialize(const Conf::YamlNode &map);
......@@ -63,6 +72,12 @@ class IAXAccount : public Account {
private:
void setAccountDetails(const std::map<std::string, std::string> &details);
/**
* Send an outgoing call invite to iax
* @param call An IAXCall pointer
*/
void iaxOutgoingInvite(IAXCall* call);
// Account login information: password
std::string password_;
IAXVoIPLink link_;
......
......@@ -36,8 +36,8 @@
#include "iaxcall.h"
#include "logger.h"
#include "account.h"
#include "manager.h"
#include "iaxaccount.h"
#include "iaxvoiplink.h"
#if HAVE_INSTANT_MESSAGING
......@@ -66,8 +66,8 @@ codecToASTFormat(int c)
}
IAXCall::IAXCall(const std::string& id, Call::CallType type,
const std::string& account_id, IAXVoIPLink* link) :
Call(id, type, account_id), format(0), session(NULL), link_(link)
IAXAccount& account, IAXVoIPLink* link) :
Call(id, type, account), format(0), session(NULL), link_(link)
{}
int IAXCall::getSupportedFormat(const std::string &accountID) const
......
......@@ -40,6 +40,7 @@
class VoIPLink;
class IAXVoIPLink;
class IAXAccount;
/**
* @file: iaxcall.h
......@@ -55,7 +56,7 @@ class IAXCall : public Call {
* @param type The type of the call
*/
IAXCall(const std::string& id, Call::CallType type,
const std::string& account_id, IAXVoIPLink* link);
IAXAccount& account, IAXVoIPLink* link);
/**
* @return int The bitwise list of supported formats
......
......@@ -49,7 +49,7 @@ IAXCallMap IAXVoIPLink::iaxCallMap_;
std::mutex IAXVoIPLink::iaxCallMapMutex_;
std::mutex IAXVoIPLink::mutexIAX = {};
IAXVoIPLink::IAXVoIPLink(const std::string& accountID) :
IAXVoIPLink::IAXVoIPLink(IAXAccount& account) :
regSession_(NULL)
, nextRefreshStamp_(0)
, rawBuffer_(RAW_BUFFER_SIZE, AudioFormat::MONO)
......@@ -57,7 +57,7 @@ IAXVoIPLink::IAXVoIPLink(const std::string& accountID) :
, encodedData_()
, resampler_(44100)
, initDone_(false)
, accountID_(accountID)
, account_(account)
, evThread_(*this)
{
srand(time(NULL)); // to get random number for RANDOM_PORT
......@@ -153,11 +153,8 @@ IAXVoIPLink::getEvent()
}
}
if (nextRefreshStamp_ and nextRefreshStamp_ < time(NULL)) {
auto account = Manager::instance().getIaxAccount(accountID_);
if (account)
sendRegister(*account);
}
if (nextRefreshStamp_ and nextRefreshStamp_ < time(NULL))
sendRegister(account_);
sendAudioFromMic();
......@@ -296,22 +293,6 @@ IAXVoIPLink::sendUnregister(Account& a, std::function<void(bool)> cb)
cb(true);
}
std::shared_ptr<Call>
IAXVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl, const std::string &account_id)
{
auto call = std::make_shared<IAXCall>(id, Call::OUTGOING, account_id, this);
call->setPeerNumber(toUrl);
call->initRecFilename(toUrl);
iaxOutgoingInvite(call.get());
call->setConnectionState(Call::PROGRESSING);
call->setState(Call::ACTIVE);
addIaxCall(call);
return call;
}
void
IAXVoIPLink::clearIaxCallMap()
{
......@@ -350,26 +331,6 @@ IAXVoIPLink::getIaxCall(const std::string& id)
return nullptr;
}
void
IAXVoIPLink::iaxOutgoingInvite(IAXCall* call)
{
std::lock_guard<std::mutex> lock(mutexIAX);
call->session = iax_session_new();
IAXAccount *account = Manager::instance().getIaxAccount(accountID_);
std::string username(account->getUsername());
std::string strNum(username + ":" + account->getPassword() + "@" + account->getHostname() + "/" + call->getPeerNumber());
/** @todo Make preference dynamic, and configurable */
int audio_format_preferred = call->getFirstMatchingFormat(call->getSupportedFormat(accountID_), accountID_);
int audio_format_capability = call->getSupportedFormat(accountID_);
iax_call(call->session, username.c_str(), username.c_str(), strNum.c_str(),
NULL, 0, audio_format_preferred, audio_format_capability);
}
std::string
IAXVoIPLink::iaxFindCallIDBySession(iax_session* session)
{
......@@ -585,8 +546,6 @@ void IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, const std::string &id)
*/
void IAXVoIPLink::iaxHandleRegReply(iax_event* event)
{
IAXAccount *account = Manager::instance().getIaxAccount(accountID_);
if (event->etype != IAX_EVENT_REGREJ && event->etype != IAX_EVENT_REGACK)
return;
......@@ -596,7 +555,7 @@ void IAXVoIPLink::iaxHandleRegReply(iax_event* event)
regSession_ = NULL;
}
account->setRegistrationState((event->etype == IAX_EVENT_REGREJ) ? RegistrationState::ERROR_AUTH : RegistrationState::REGISTERED);
account_.setRegistrationState((event->etype == IAX_EVENT_REGREJ) ? RegistrationState::ERROR_AUTH : RegistrationState::REGISTERED);
if (event->etype == IAX_EVENT_REGACK)
nextRefreshStamp_ = time(NULL) + (event->ies.refresh ? event->ies.refresh : 60);
......@@ -604,6 +563,7 @@ void IAXVoIPLink::iaxHandleRegReply(iax_event* event)
void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
{
const auto accountID = account_.getAccountID();
std::shared_ptr<IAXCall> call;
std::string id;
int format;
......@@ -612,7 +572,7 @@ void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
case IAX_EVENT_CONNECT:
id = Manager::instance().getNewCallID();
call = std::make_shared<IAXCall>(id, Call::INCOMING, accountID_, this);
call = std::make_shared<IAXCall>(id, Call::INCOMING, account_, this);
call->session = event->session;
call->setConnectionState(Call::PROGRESSING);
......@@ -627,12 +587,12 @@ void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
if (event->ies.calling_number)
call->initRecFilename(std::string(event->ies.calling_number));
Manager::instance().incomingCall(*call, accountID_);
Manager::instance().incomingCall(*call, accountID);
format = call->getFirstMatchingFormat(event->ies.format, accountID_);
format = call->getFirstMatchingFormat(event->ies.format, accountID);
if (!format)
format = call->getFirstMatchingFormat(event->ies.capability, accountID_);
format = call->getFirstMatchingFormat(event->ies.capability, accountID);
iax_accept(event->session, format);
iax_ring_announce(event->session);
......
......@@ -67,7 +67,7 @@ typedef std::map<std::string, std::shared_ptr<IAXCall> > IAXCallMap;
class IAXVoIPLink : public VoIPLink {
public:
IAXVoIPLink(const std::string& accountID);
IAXVoIPLink(IAXAccount& account);
~IAXVoIPLink();
/**
......@@ -113,14 +113,6 @@ class IAXVoIPLink : public VoIPLink {
*/
virtual void sendUnregister(Account& a, std::function<void(bool)> cb = std::function<void(bool)>());
/**
* Create a new outgoing call
* @param id The ID of the call
* @param toUrl The address to call
* @return Call* A pointer on the call
*/
virtual std::shared_ptr<Call> newOutgoingCall(const std::string& id, const std::string& toUrl, const std::string &account_id);
/**
* Cancel a call
* @param id The ID of the call
......@@ -210,12 +202,6 @@ class IAXVoIPLink : public VoIPLink {
*/
void sendAudioFromMic();
/**
* Send an outgoing call invite to iax
* @param call An IAXCall pointer
*/
void iaxOutgoingInvite(IAXCall* call);
/** registration session : 0 if not register */
iax_session* regSession_;
......@@ -237,7 +223,7 @@ class IAXVoIPLink : public VoIPLink {
*/
bool initDone_;
const std::string accountID_;
IAXAccount& account_;
/**
* Threading object
......
......@@ -352,17 +352,17 @@ bool ManagerImpl::outgoingCall(const std::string& account_id,
DEBUG("Selecting account %s", account_id.c_str());
// fallback using the default sip account if the specied doesn't exist
std::string use_account_id;
if (!accountExists(account_id)) {
Account* account = getAccount(account_id);
if (!account) {
WARN("Account does not exist, trying with default SIP account");
use_account_id = SIPAccount::IP2IP_PROFILE;
}
else {
use_account_id = account_id;
}
account = getAccount(SIPAccount::IP2IP_PROFILE);
setIPToIPForCall(call_id, true);
} else
setIPToIPForCall(call_id, false);
try {
auto call = getAccountLink(account_id)->newOutgoingCall(call_id, to_cleaned, use_account_id);
DEBUG("New outgoing call to %s", to_cleaned.c_str());
auto call = account->newOutgoingCall(call_id, to_cleaned);
// try to reverse match the peer name using the cache
if (call->getDisplayName().empty()) {
......
......@@ -36,8 +36,11 @@
#include "config.h"
#endif
#include "sdp.h"
#include "sipvoiplink.h"
#include "sipcall.h"
#include "sip_utils.h"
#include "array_size.h"
#ifdef SFL_PRESENCE
#include "sippresence.h"
......@@ -152,7 +155,6 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
alias_ = IP2IP_PROFILE;
}
SIPAccount::~SIPAccount()
{
setTransport();
......@@ -162,7 +164,6 @@ SIPAccount::~SIPAccount()
#endif
}
static std::array<std::unique_ptr<Conf::ScalarNode>, 2>
serializeRange(Conf::MappingNode &accountMap, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range)
{
......@@ -201,6 +202,165 @@ unserializeRange(const Conf::YamlNode &mapNode, const char *minKey, const char *
updateRange(tmpMin, tmpMax, range);
}
std::shared_ptr<Call>
SIPAccount::newOutgoingCall(const std::string& id,
const std::string& toUrl)
{
std::string to;
std::string toUri;
int family;
if (isIP2IP()) {
bool ipv6 = false;
#if HAVE_IPV6
ipv6 = IpAddr::isIpv6(toUrl);
#endif
to = ipv6 ? IpAddr(toUrl).toString(false, true) : toUrl;
toUri = getToUri(to);
family = ipv6 ? pj_AF_INET6() : pj_AF_INET();
DEBUG("New %s IP to IP call to %s", ipv6?"IPv6":"IPv4", to.c_str());
}
else {
to = toUrl;
// If toUrl is not a well formatted sip URI, use account information to process it
if (toUrl.find("sip:") != std::string::npos or
toUrl.find("sips:") != std::string::npos)
toUri = toUrl;
else
toUri = getToUri(to);
// FIXME : for now, use the same address family as the SIP tranport
family = pjsip_transport_type_get_af(getTransportType());
DEBUG("UserAgent: New registered account call to %s", toUrl.c_str());
}
auto call = std::make_shared<SIPCall>(id, Call::OUTGOING, *this);
call->setIPToIP(isIP2IP());
call->setPeerNumber(toUri);
call->initRecFilename(to);
const auto localAddress = ip_utils::getInterfaceAddr(getLocalInterface(), family);
call->setCallMediaLocal(localAddress);
// May use the published address as well
const auto addrSdp = isStunEnabled() or (not getPublishedSameasLocal()) ?
getPublishedIpAddress() : localAddress;
// Initialize the session using ULAW as default codec in case of early media
// The session should be ready to receive media once the first INVITE is sent, before
// the session initialization is completed
sfl::AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW);
if (!ac)
throw VoipLinkException("Could not instantiate codec for early media");
std::vector<sfl::AudioCodec *> audioCodecs;
audioCodecs.push_back(ac);
try {
call->getAudioRtp().initConfig();
call->getAudioRtp().initSession();
if (isStunEnabled())
call->updateSDPFromSTUN();
call->getAudioRtp().initLocalCryptoInfo();
call->getAudioRtp().start(audioCodecs);
} catch (...) {
throw VoipLinkException("Could not start rtp session for early media");
}
// Building the local SDP offer
auto localSDP = call->getLocalSDP();
if (getPublishedSameasLocal())
localSDP->setPublishedIP(addrSdp);
else
localSDP->setPublishedIP(getPublishedAddress());
const bool created = localSDP->createOffer(getActiveAudioCodecs(), getActiveVideoCodecs());
if (not created or not SIPStartCall(call))
throw VoipLinkException("Could not send outgoing INVITE request for new call");
return call;
}
bool
SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
{
std::string toUri(call->getPeerNumber()); // expecting a fully well formed sip uri
pj_str_t pjTo = pj_str((char*) toUri.c_str());
// Create the from header
std::string from(getFromUri());
pj_str_t pjFrom = pj_str((char*) from.c_str());
pj_str_t pjContact(getContactHeader());
const std::string debugContactHeader(pj_strbuf(&pjContact), pj_strlen(&pjContact));
DEBUG("contact header: %s / %s -> %s",
debugContactHeader.c_str(), from.c_str(), toUri.c_str());
pjsip_dialog *dialog = NULL;
if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog) != PJ_SUCCESS) {
ERROR("Unable to create SIP dialogs for user agent client when "
"calling %s", toUri.c_str());
return false;
}
pj_str_t subj_hdr_name = CONST_PJ_STR("Subject");
pjsip_hdr* subj_hdr = (pjsip_hdr*) pjsip_parse_hdr(dialog->pool, &subj_hdr_name, (char *) "Phone call", 10, NULL);
pj_list_push_back(&dialog->inv_hdr, subj_hdr);
if (pjsip_inv_create_uac(dialog, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv) != PJ_SUCCESS) {
ERROR("Unable to create invite session for user agent client");
return false;
}
updateDialogViaSentBy(dialog);
if (hasServiceRoute())
pjsip_dlg_set_route_set(dialog, sip_utils::createRouteSet(getServiceRoute(), call->inv->pool));
if (hasCredentials() and pjsip_auth_clt_set_credentials(&dialog->auth_sess, getCredentialCount(), getCredInfo()) != PJ_SUCCESS) {
ERROR("Could not initialize credentials for invite session authentication");
return false;
}
call->inv->mod_data[SIPVoIPLink::instance().getMod()->id] = call.get();
pjsip_tx_data *tdata;
if (pjsip_inv_invite(call->inv, &tdata) != PJ_SUCCESS) {
ERROR("Could not initialize invite messager for this call");
return false;
}
const pjsip_tpselector tp_sel = getTransportSelector();
if (pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
ERROR("Unable to associate transport for invite session dialog");
return false;
}
if (pjsip_inv_send_msg(call->inv, tdata) != PJ_SUCCESS) {
ERROR("Unable to send invite message for this call");
return false;
}
call->setConnectionState(Call::PROGRESSING);
call->setState(Call::ACTIVE);
SIPVoIPLink::instance().addSipCall(call);
return true;
}
void SIPAccount::serialize(Conf::YamlEmitter &emitter)
{
using namespace Conf;
......
......@@ -113,6 +113,7 @@ namespace Conf {
class SIPVoIPLink;
class SIPPresence;
class SIPCall;
/**
......@@ -137,6 +138,15 @@ class SIPAccount : public Account {
SIPAccount(const std::string& accountID, bool presenceEnabled);
~SIPAccount();
/**
* Create a new outgoing call
* @param id The ID of the call
* @param toUrl The address to call
* @return Call* A pointer on the call
*/
std::shared_ptr<Call> newOutgoingCall(const std::string& id,
const std::string& toUrl);
virtual VoIPLink* getVoIPLink();
pjsip_host_port getHostPortFromSTUN(pj_pool_t *pool);
......@@ -599,6 +609,16 @@ class SIPAccount : public Account {
NON_COPYABLE(SIPAccount);
std::shared_ptr<Call> newRegisteredAccountCall(const std::string& id,
const std::string& toUrl);
/**
* Start a SIP Call
* @param call The current call
* @return true if all is correct
*/
bool SIPStartCall(std::shared_ptr<SIPCall>& call);
void usePublishedAddressPortInVIA();
bool fullMatch(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
bool userMatch(const std::string &username) const;
......
......@@ -63,26 +63,6 @@ static const int INCREMENT_SIZE = INITIAL_SIZE;
* Given a SIP call ID (usefull for transaction sucha as transfer)*/
static std::map<std::string, std::string> transferCallID;
static void
updateSDPFromSTUN(SIPCall &call, SIPAccount &account, const SipTransport &transport)
{
std::vector<long> socketDescriptors(call.getAudioRtp().getSocketDescriptors());
try {
std::vector<pj_sockaddr> stunPorts(transport.getSTUNAddresses(account, socketDescriptors));
// FIXME: get video sockets
//stunPorts.resize(4);
account.setPublishedAddress(stunPorts[0]);
// published IP MUST be updated first, since RTCP depends on it
call.getLocalSDP()->setPublishedIP(account.getPublishedAddress());
call.getLocalSDP()->updatePorts(stunPorts);
} catch (const std::runtime_error &e) {
ERROR("%s", e.what());
}
}
static void
stopRtpIfCurrent(SIPCall& call)
{
......@@ -124,15 +104,16 @@ dtmfSend(SIPCall &call, char code, const std::string &dtmf)
}
SIPCall::SIPCall(const std::string& id, Call::CallType type,
pj_caching_pool *caching_pool, const std::string &account_id) :
Call(id, type, account_id)
SIPAccount& account) :
Call(id, type, account)
, inv(NULL)
, audiortp_(this)
#ifdef SFL_VIDEO
// The ID is used to associate video streams to calls
, videortp_(id, getSettings())
#endif
, pool_(pj_pool_create(&caching_pool->factory, id.c_str(), INITIAL_SIZE, INCREMENT_SIZE, NULL))
, pool_(pj_pool_create(&SIPVoIPLink::instance().getCachingPool()->factory,
id.c_str(), INITIAL_SIZE, INCREMENT_SIZE, NULL))
, local_sdp_(new Sdp(pool_))
, contactBuffer_()
, contactHeader_{contactBuffer_, 0}
......@@ -144,6 +125,40 @@ SIPCall::~SIPCall()
pj_pool_release(pool_);
}
SIPAccount&
SIPCall::getSIPAccount() const
{
return static_cast<SIPAccount&>(getAccount());
}