Merge branch 'master' into merge-upstream

Conflicts:
	daemon/src/audio/codecs/audiocodec.h
	daemon/src/audio/codecs/audiocodecfactory.cpp
	daemon/src/dbus/callmanager.cpp
	daemon/src/dbus/callmanager.h
	daemon/src/managerimpl.cpp
	daemon/src/sip/sipvoiplink.cpp
This commit is contained in:
alision
2013-06-19 16:08:38 -04:00
100 changed files with 6536 additions and 746 deletions

View File

@ -62,8 +62,10 @@ Sdp::Sdp(pj_pool_t *pool)
, sessionVideoMedia_()
, localIpAddr_()
, remoteIpAddr_()
, localAudioPort_(0)
, localVideoPort_(0)
, localAudioDataPort_(0)
, localAudioControlPort_(0)
, localVideoDataPort_(0)
, localVideoControlPort_(0)
, remoteAudioPort_(0)
, remoteVideoPort_(0)
, zrtpHelloHash_()
@ -205,7 +207,7 @@ Sdp::setMediaDescriptorLines(bool audio)
med->desc.media = audio ? pj_str((char*) "audio") : pj_str((char*) "video");
med->desc.port_count = 1;
med->desc.port = audio ? localAudioPort_ : localVideoPort_;
med->desc.port = audio ? localAudioDataPort_ : localVideoDataPort_;
// in case of sdes, media are tagged as "RTP/SAVP", RTP/AVP elsewhere
med->desc.transport = pj_str(srtpCrypto_.empty() ? (char*) "RTP/AVP" : (char*) "RTP/SAVP");
@ -283,10 +285,8 @@ Sdp::setMediaDescriptorLines(bool audio)
void Sdp::addRTCPAttribute(pjmedia_sdp_media *med)
{
// FIXME: get this from CCRTP directly, don't just assume that the RTCP port is
// RTP + 1
std::ostringstream os;
os << localIpAddr_ << ":" << (localAudioPort_ + 1);
os << localIpAddr_ << ":" << localAudioControlPort_;
const std::string str(os.str());
pj_str_t input_str = pj_str((char*) str.c_str());
pj_sockaddr outputAddr;
@ -300,6 +300,15 @@ void Sdp::addRTCPAttribute(pjmedia_sdp_media *med)
pjmedia_sdp_attr_add(&med->attr_count, med->attr, attr);
}
void
Sdp::updatePorts(const std::vector<pj_sockaddr_in> &sockets)
{
localAudioDataPort_ = pj_ntohs(sockets[0].sin_port);
localAudioControlPort_ = pj_ntohs(sockets[1].sin_port);
localVideoDataPort_ = pj_ntohs(sockets[2].sin_port);
localVideoControlPort_ = pj_ntohs(sockets[3].sin_port);
}
void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med)
{

View File

@ -163,13 +163,17 @@ class Sdp {
}
void setLocalPublishedAudioPort(int port) {
localAudioPort_ = port;
localAudioDataPort_ = port;
localAudioControlPort_ = port + 1;
}
void setLocalPublishedVideoPort (int port) {
localVideoPort_ = port;
localVideoDataPort_ = port;
localVideoControlPort_ = port + 1;
}
void updatePorts(const std::vector<pj_sockaddr_in> &sockets);
/**
* Return IP of destination
* @return const std:string The remote IP address
@ -202,6 +206,10 @@ class Sdp {
return remoteVideoPort_;
}
unsigned int getLocalVideoPort() const {
return localVideoDataPort_;
}
void addAttributeToLocalAudioMedia(const char *attr);
void removeAttributeFromLocalAudioMedia(const char *attr);
void addAttributeToLocalVideoMedia(const char *attr);
@ -304,8 +312,10 @@ class Sdp {
std::string localIpAddr_;
std::string remoteIpAddr_;
int localAudioPort_;
int localVideoPort_;
int localAudioDataPort_;
int localAudioControlPort_;
int localVideoDataPort_;
int localVideoControlPort_;
unsigned int remoteAudioPort_;
unsigned int remoteVideoPort_;

View File

@ -126,12 +126,21 @@ sip_utils::stripSipUriPrefix(std::string& sipUri)
size_t found = sipUri.find(SIP_PREFIX);
if (found != std::string::npos)
sipUri.erase(found, found + (sizeof SIP_PREFIX) - 1);
sipUri.erase(found, (sizeof SIP_PREFIX) - 1);
// URI may or may not be between brackets
found = sipUri.find("<");
if (found != std::string::npos)
sipUri.erase(found, 1);
found = sipUri.find("@");
if (found != std::string::npos)
sipUri.erase(found);
found = sipUri.find(">");
if (found != std::string::npos)
sipUri.erase(found, 1);
}
std::vector<std::string>

View File

@ -37,7 +37,7 @@
#include <pjsip/sip_msg.h>
class pjsip_msg;
struct pjsip_msg;
namespace sip_utils {
/**

View File

@ -318,7 +318,7 @@ void SIPAccount::unserialize(const Conf::YamlNode &mapNode)
if (not isIP2IP()) mapNode.getValue(MAILBOX_KEY, &mailBox_);
mapNode.getValue(AUDIO_CODECS_KEY, &audioCodecStr_);
// Update codec list which one is used for SDP offer
setActiveAudioCodecs(ManagerImpl::split_string(audioCodecStr_));
setActiveAudioCodecs(split_string(audioCodecStr_));
#ifdef SFL_VIDEO
YamlNode *videoCodecsNode(mapNode.getValue(VIDEO_CODECS_KEY));

View File

@ -316,9 +316,6 @@ class SIPAccount : public Account {
pj_uint16_t getStunPort() const {
return stunPort_;
}
void setStunPort(pj_uint16_t port) {
stunPort_ = port;
}
/**
* @return bool Tells if current transport for that
@ -442,6 +439,11 @@ class SIPAccount : public Account {
return publishedIpAddress_;
}
void setPublishedAddress(const std::string &ip_addr) {
publishedIpAddress_ = ip_addr;
}
std::string getServiceRoute() const {
return serviceRoute_;
}

View File

@ -45,7 +45,8 @@ namespace {
}
SIPCall::SIPCall(const std::string& id, Call::CallType type,
pj_caching_pool *caching_pool) : Call(id, type)
pj_caching_pool *caching_pool, const std::string &account_id) :
Call(id, type, account_id)
, inv(NULL)
, audiortp_(this)
#ifdef SFL_VIDEO

View File

@ -44,10 +44,10 @@
#include "noncopyable.h"
class pjsip_evsub;
class pj_caching_pool;
class pj_pool_t;
class pjsip_inv_session;
struct pjsip_evsub;
struct pj_caching_pool;
struct pj_pool_t;
struct pjsip_inv_session;
class Sdp;
/**
@ -63,7 +63,8 @@ class SIPCall : public Call {
* @param type The type of the call. Could be Incoming
* Outgoing
*/
SIPCall(const std::string& id, Call::CallType type, pj_caching_pool *caching_pool);
SIPCall(const std::string& id, Call::CallType type,
pj_caching_pool *caching_pool, const std::string &account_id);
/**
* Destructor

View File

@ -465,6 +465,27 @@ pjsip_tpselector *SipTransport::createTransportSelector(pjsip_transport *transpo
return tp;
}
std::vector<pj_sockaddr_in>
SipTransport::getSTUNAddresses(const SIPAccount &account,
std::vector<long> &socketDescriptors) const
{
const pj_str_t serverName = account.getStunServerName();
const pj_uint16_t port = account.getStunPort();
std::vector<pj_sockaddr_in> result(socketDescriptors.size());
if (pjstun_get_mapped_addr(&cp_->factory, socketDescriptors.size(), &socketDescriptors[0],
&serverName, port, &serverName, port, &result[0]) != PJ_SUCCESS)
throw std::runtime_error("Can't contact STUN server");
for (std::vector<pj_sockaddr_in>::const_iterator it = result.begin();
it != result.end(); ++it)
WARN("STUN PORTS: %ld", pj_ntohs(it->sin_port));
return result;
}
pjsip_transport *SipTransport::createStunTransport(SIPAccount &account)
{
#if HAVE_DBUS
@ -480,7 +501,6 @@ pjsip_transport *SipTransport::createStunTransport(SIPAccount &account)
pj_str_t serverName = account.getStunServerName();
pj_uint16_t port = account.getStunPort();
DEBUG("Create STUN transport server name: %s, port: %d", serverName, port);
RETURN_IF_STUN_FAIL(createStunResolver(serverName, port) == PJ_SUCCESS, "Can't resolve STUN server");
pj_sock_t sock = PJ_INVALID_SOCKET;

View File

@ -112,6 +112,13 @@ class SipTransport {
*/
void shutdownSTUNResolver(SIPAccount &account);
/**
* This function returns a list of STUN mapped sockets for
* a given set of socket file descriptors */
std::vector<pj_sockaddr_in>
getSTUNAddresses(const SIPAccount &account,
std::vector<long> &socks) const;
/**
* This function unset the transport for a given account.
*/

View File

@ -40,6 +40,7 @@
#include "sipvoiplink.h"
#include "array_size.h"
#include "manager.h"
#include "map_utils.h"
#include "logger.h"
#include "scoped_lock.h"
@ -218,6 +219,23 @@ void showLog(int level, const char *data, int len)
}
#endif
void updateSDPFromSTUN(SIPCall &call, SIPAccount &account, const SipTransport &transport)
{
std::vector<long> socketDescriptors(call.getAudioRtp().getSocketDescriptors());
try {
std::vector<pj_sockaddr_in> stunPorts(transport.getSTUNAddresses(account, socketDescriptors));
// FIXME: get video sockets
stunPorts.resize(4);
account.setPublishedAddress(pj_inet_ntoa(stunPorts[0].sin_addr));
call.getLocalSDP()->updatePorts(stunPorts);
} catch (const std::runtime_error &e) {
ERROR("%s", e.what());
}
}
pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
{
@ -302,8 +320,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
Manager::instance().hookPreference.runHook(rdata->msg_info.msg);
SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_);
Manager::instance().associateCallToAccount(call->getCallId(), account_id);
SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_, account_id);
// May use the published address as well
std::string addrToUse = SipTransport::getInterfaceAddrFromName(account->getLocalInterface());
@ -318,11 +335,10 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
std::string peerNumber(tmp, std::min(length, sizeof tmp));
sip_utils::stripSipUriPrefix(peerNumber);
std::string remote_user(sip_from_uri->user.ptr, sip_from_uri->user.slen);
std::string remove_hostname(sip_from_uri->host.ptr, sip_from_uri->host.slen);
if (remote_user.size() > 0 && remove_hostname.size() > 0) {
peerNumber = remote_user + "@" + remove_hostname;
}
const std::string remote_user(sip_from_uri->user.ptr, sip_from_uri->user.slen);
const std::string remote_hostname(sip_from_uri->host.ptr, sip_from_uri->host.slen);
if (not remote_user.empty() and not remote_hostname.empty())
peerNumber = remote_user + "@" + remote_hostname;
call->setConnectionState(Call::PROGRESSING);
call->setPeerNumber(peerNumber);
@ -342,6 +358,9 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
return PJ_FALSE;
}
if (account->isStunEnabled())
updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport);
if (body and body->len > 0 and call->getAudioRtp().isSdesEnabled()) {
std::string sdpOffer(static_cast<const char*>(body->data), body->len);
size_t start = sdpOffer.find("a=crypto:");
@ -722,14 +741,24 @@ void SIPVoIPLink::sendRegister(Account *a)
std::string contact = account->getContactHeader();
pj_str_t pjContact = pj_str((char*) contact.c_str());
#ifndef __ANDROID__
#warning update pj_sip
if (not received.empty() and received != account->getPublishedAddress()) {
if (account->isStunEnabled()) {
DEBUG("Setting VIA sent-by to %s:%u", account->transport_->local_name.host.ptr, account->transport_->local_name.port);
if (pjsip_regc_set_via_sent_by(regc, &account->transport_->local_name, account->transport_) != PJ_SUCCESS)
throw VoipLinkException("Unable to set the \"sent-by\" field");
} else if (not received.empty() and received != account->getPublishedAddress()) {
DEBUG("Setting VIA sent-by to %s:%d", received.c_str(), account->getRPort());
if (pjsip_regc_set_via_sent_by(regc, account->getViaAddr(), account->transport_) != PJ_SUCCESS)
throw VoipLinkException("Unable to set the \"sent-by\" field");
}
#else
#warning update pj_sip
#endif
if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account->getRegistrationExpire()) != PJ_SUCCESS)
throw VoipLinkException("Unable to initialize account registration structure");
@ -852,7 +881,7 @@ bool isValidIpAddress(const std::string &address)
}
Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl)
Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl, const std::string &account_id)
{
DEBUG("New outgoing call to %s", toUrl.c_str());
std::string toCpy = toUrl;
@ -863,10 +892,9 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU
Manager::instance().setIPToIPForCall(id, IPToIP);
if (IPToIP) {
Manager::instance().associateCallToAccount(id, SIPAccount::IP2IP_PROFILE);
return SIPNewIpToIpCall(id, toUrl);
return SIPNewIpToIpCall(id, toCpy);
} else {
return newRegisteredAccountCall(id, toUrl);
return newRegisteredAccountCall(id, toUrl, account_id);
}
}
@ -879,7 +907,7 @@ Call *SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to
if (!account)
throw VoipLinkException("Could not retrieve default account for IP2IP call");
SIPCall *call = new SIPCall(id, Call::OUTGOING, cp_);
SIPCall *call = new SIPCall(id, Call::OUTGOING, cp_, SIPAccount::IP2IP_PROFILE);
call->setIPToIP(true);
call->initRecFilename(to);
@ -920,16 +948,16 @@ Call *SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to
return call;
}
Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::string& toUrl)
Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::string& toUrl, const std::string &account_id)
{
DEBUG("UserAgent: New registered account call to %s", toUrl.c_str());
SIPAccount *account = Manager::instance().getSipAccount(Manager::instance().getAccountFromCall(id));
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (account == NULL) // TODO: We should investigate how we could get rid of this error and create a IP2IP call instead
throw VoipLinkException("Could not get account for this call");
SIPCall* call = new SIPCall(id, Call::OUTGOING, cp_);
SIPCall* call = new SIPCall(id, Call::OUTGOING, cp_, account->getAccountID());
// If toUri is not a well formatted sip URI, use account information to process it
std::string toUri;
@ -964,6 +992,10 @@ Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::st
try {
call->getAudioRtp().initConfig();
call->getAudioRtp().initSession();
if (account->isStunEnabled())
updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport);
call->getAudioRtp().initLocalCryptoInfo();
call->getAudioRtp().start(audioCodecs);
} catch (...) {
@ -1020,7 +1052,7 @@ SIPVoIPLink::hangup(const std::string& id, int reason)
if (!call)
return;
std::string account_id(Manager::instance().getAccountFromCall(id));
std::string account_id(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (account == NULL)
@ -1164,6 +1196,13 @@ SIPVoIPLink::offhold(const std::string& id)
call->getAudioRtp().initConfig();
call->getAudioRtp().initSession();
const std::string account_id(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (account and account->isStunEnabled())
updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport);
call->getAudioRtp().restoreLocalContext();
call->getAudioRtp().initLocalCryptoInfoOnOffHold();
call->getAudioRtp().start(audioCodecs);
@ -1218,6 +1257,17 @@ SIPVoIPLink::clearSipCallMap()
sipCallMap_.clear();
}
std::vector<std::string>
SIPVoIPLink::getCallIDs()
{
std::vector<std::string> v;
sfl::ScopedLock m(sipCallMapMutex_);
map_utils::vectorFromMapKeys(sipCallMap_, v);
return v;
}
void SIPVoIPLink::addSipCall(SIPCall* call)
{
if (!call)
@ -1323,7 +1373,7 @@ SIPVoIPLink::transfer(const std::string& id, const std::string& to)
call->stopRecording();
std::string account_id(Manager::instance().getAccountFromCall(id));
std::string account_id(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (account == NULL)
@ -1515,14 +1565,15 @@ SIPVoIPLink::requestKeyframe(const std::string &callID)
void
SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code)
{
std::string accountID(Manager::instance().getAccountFromCall(id));
SIPCall *call = getSipCall(id);
if (!call)
return;
const std::string accountID(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(accountID);
if (!account)
return;
SIPCall *call = getSipCall(id);
if (!call)
return;
dtmfSend(*call, code, account->getDtmfType());
}
@ -1530,8 +1581,8 @@ SIPVoIPLink::carryingDTMFdigits(const std::string& id, char code)
bool
SIPVoIPLink::SIPStartCall(SIPCall *call)
{
std::string id(Manager::instance().getAccountFromCall(call->getCallId()));
SIPAccount *account = Manager::instance().getSipAccount(id);
std::string account_id(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (account == NULL) {
ERROR("Account is NULL in SIPStartCall");
@ -1682,7 +1733,7 @@ void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *ev)
// After we sent or received a ACK - The connection is established
link->SIPCallAnswered(call, ev->body.tsx_state.src.rdata);
} else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
std::string accId(Manager::instance().getAccountFromCall(call->getCallId()));
std::string accId(call->getAccountId());
switch (inv->cause) {
// The call terminates normally - BYE / CANCEL
@ -1719,7 +1770,7 @@ void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *off
if (!call)
return;
std::string accId(Manager::instance().getAccountFromCall(call->getCallId()));
std::string accId(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(accId);
if (!account)
return;
@ -1737,7 +1788,7 @@ void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
SIPCall *call = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]);
if (!call)
return;
std::string accountid(Manager::instance().getAccountFromCall(call->getCallId()));
std::string accountid(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(accountid);
if (!account)
@ -1840,7 +1891,7 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status)
Manager::instance().getVideoControls()->stopPreview();
call->getVideoRtp().updateSDP(*call->getLocalSDP());
call->getVideoRtp().updateDestination(call->getLocalSDP()->getRemoteIP(), call->getLocalSDP()->getRemoteVideoPort());
call->getVideoRtp().start();
call->getVideoRtp().start(call->getLocalSDP()->getLocalVideoPort());
#endif
// Get the crypto attribute containing srtp's cryptographic context (keys, cipher)
@ -1881,11 +1932,15 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status)
call->getAudioRtp().stop();
call->getAudioRtp().setSrtpEnabled(false);
std::string accountID = Manager::instance().getAccountFromCall(call->getCallId());
const std::string accountID = call->getAccountId();
SIPAccount *sipaccount = Manager::instance().getSipAccount(accountID);
if (sipaccount and sipaccount->getSrtpFallback())
if (sipaccount and sipaccount->getSrtpFallback()) {
call->getAudioRtp().initSession();
if (sipaccount->isStunEnabled())
updateSDPFromSTUN(*call, *sipaccount, SIPVoIPLink::instance()->sipTransport);
}
}
#endif // HAVE_SDES
@ -2215,7 +2270,8 @@ void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata)
}
try {
SIPVoIPLink::instance()->newOutgoingCall(Manager::instance().getNewCallID(), std::string(refer_to->hvalue.ptr, refer_to->hvalue.slen));
SIPVoIPLink::instance()->newOutgoingCall(Manager::instance().getNewCallID(),
std::string(refer_to->hvalue.ptr, refer_to->hvalue.slen), currentCall->getAccountId());
Manager::instance().hangupCall(currentCall->getCallId());
} catch (const VoipLinkException &e) {
ERROR("%s", e.what());
@ -2295,30 +2351,28 @@ void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event)
}
namespace {
// returns port in range [10500, 64998]
unsigned int getRandomPort()
// returns even number in range [lower, upper]
unsigned int getRandomEvenNumber(int lower, int upper)
{
return ((rand() % 27250) + 5250) * 2;
const unsigned halfUpper = upper * 0.5;
const unsigned halfLower = lower * 0.5;
return 2 * (halfLower + rand() % (halfUpper - halfLower + 1));
}
}
void setCallMediaLocal(SIPCall* call, const std::string &localIP)
{
std::string account_id(Manager::instance().getAccountFromCall(call->getCallId()));
std::string account_id(call->getAccountId());
SIPAccount *account = Manager::instance().getSipAccount(account_id);
if (!account)
return;
// Reference: http://www.cs.columbia.edu/~hgs/rtp/faq.html#ports
// We only want to set ports to new values if they haven't been set
if (call->getLocalAudioPort() == 0) {
const unsigned int callLocalAudioPort = getRandomPort();
const unsigned int callLocalExternAudioPort = account->isStunEnabled()
? account->getStunPort()
: callLocalAudioPort;
const unsigned callLocalAudioPort = getRandomEvenNumber(16384, 32766);
call->setLocalAudioPort(callLocalAudioPort);
call->getLocalSDP()->setLocalPublishedAudioPort(callLocalExternAudioPort);
call->getLocalSDP()->setLocalPublishedAudioPort(callLocalAudioPort);
}
call->setLocalIp(localIP);
@ -2326,10 +2380,9 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP)
#ifdef SFL_VIDEO
if (call->getLocalVideoPort() == 0) {
// https://projects.savoirfairelinux.com/issues/17498
const unsigned int MAX_VIDEO_PORT = 20001;
unsigned int callLocalVideoPort = 0;
unsigned int callLocalVideoPort;
do
callLocalVideoPort = getRandomPort() % MAX_VIDEO_PORT;
callLocalVideoPort = getRandomEvenNumber(49152, 65534);
while (call->getLocalAudioPort() == callLocalVideoPort);
call->setLocalVideoPort(callLocalVideoPort);

View File

@ -100,6 +100,10 @@ class SIPVoIPLink : public VoIPLink {
*/
virtual bool getEvent();
/* Returns a list of all callIDs */
std::vector<std::string>
getCallIDs();
/**
* Return the internal account map for this VOIP link
*/
@ -132,7 +136,7 @@ class SIPVoIPLink : public VoIPLink {
* @param toUrl The Sip address of the recipient of the call
* @return Call* The current call
*/
virtual Call* newOutgoingCall(const std::string& id, const std::string& toUrl);
virtual Call* newOutgoingCall(const std::string& id, const std::string& toUrl, const std::string &account_id);
/**
* Start a new SIP call using the IP2IP profile
@ -146,7 +150,7 @@ class SIPVoIPLink : public VoIPLink {
* @param The call id
* @param The target sip uri
*/
Call *newRegisteredAccountCall(const std::string& id, const std::string& toUrl);
Call *newRegisteredAccountCall(const std::string& id, const std::string& toUrl, const std::string &account_id);
/**
* Answer the call
@ -272,6 +276,7 @@ class SIPVoIPLink : public VoIPLink {
#endif
void clearSipCallMap();
void addSipCall(SIPCall* call);
SIPCall* getSipCall(const std::string& id);
SIPCall* tryGetSipCall(const std::string& id);
void removeSipCall(const std::string &id);