mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
Merge branch 'master' of git+ssh://git.sflphone.org/var/repos/sflphone/git/sflphone
Conflicts: daemon/src/sip/sipvoiplink.cpp
This commit is contained in:
@ -38,7 +38,6 @@ Account::Account(const std::string& accountID, const std::string &type) :
|
||||
, username_()
|
||||
, hostname_()
|
||||
, alias_()
|
||||
, link_(NULL)
|
||||
, enabled_(true)
|
||||
, type_(type)
|
||||
, registrationState_(Unregistered)
|
||||
|
@ -71,7 +71,7 @@ static const char *const CONFIG_ACCOUNT_TYPE = "Account.type";
|
||||
static const char *const CONFIG_ACCOUNT_ALIAS = "Account.alias";
|
||||
static const char *const CONFIG_ACCOUNT_MAILBOX = "Account.mailbox";
|
||||
static const char *const CONFIG_ACCOUNT_ENABLE = "Account.enable";
|
||||
static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.expire";
|
||||
static const char *const CONFIG_ACCOUNT_REGISTRATION_EXPIRE = "Account.registrationExpire";
|
||||
static const char *const CONFIG_CREDENTIAL_NUMBER = "Credential.count";
|
||||
static const char *const ACCOUNT_DTMF_TYPE = "Account.dtmfType";
|
||||
static const char *const CONFIG_RINGTONE_PATH = "Account.ringtonePath";
|
||||
@ -188,9 +188,7 @@ class Account : public Serializable {
|
||||
* Get the voiplink pointer
|
||||
* @return VoIPLink* the pointer or 0
|
||||
*/
|
||||
VoIPLink* getVoIPLink() {
|
||||
return link_;
|
||||
}
|
||||
virtual VoIPLink* getVoIPLink() = 0;
|
||||
|
||||
/**
|
||||
* Register the underlying VoIPLink. Launch the event listener.
|
||||
@ -324,11 +322,6 @@ class Account : public Serializable {
|
||||
*/
|
||||
std::string alias_;
|
||||
|
||||
/**
|
||||
* Voice over IP Link contains a listener thread and calls
|
||||
*/
|
||||
VoIPLink* link_;
|
||||
|
||||
/**
|
||||
* Tells if the link is enabled, active.
|
||||
* This implies the link will be initialized on startup.
|
||||
|
@ -155,7 +155,7 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory()
|
||||
if (envDir)
|
||||
dirToScan.push_back(std::string(envDir) + DIR_SEPARATOR_STR);
|
||||
|
||||
const char *progDir = get_program_dir();
|
||||
const char *progDir = fileutils::get_program_dir();
|
||||
|
||||
if (progDir)
|
||||
dirToScan.push_back(std::string(progDir) + DIR_SEPARATOR_STR + "audio/codecs/");
|
||||
|
@ -190,7 +190,7 @@
|
||||
<tp:docstring>
|
||||
Send account registration (REGISTER) to the registrar.
|
||||
</tp:docstring>
|
||||
the account if expire=1, unregister if expire=0.
|
||||
Register the account if enable=true, unregister if enable=false.
|
||||
|
||||
@param[in] input accountID
|
||||
-->
|
||||
@ -199,10 +199,10 @@
|
||||
The account ID
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="i" name="expire" direction="in">
|
||||
<arg type="b" name="enable" direction="in">
|
||||
<tp:docstring>
|
||||
<p>To register, expire must be 1.</p>
|
||||
<p>To un-register, expire must be 0.</p>
|
||||
<p>To register, enable must be true.</p>
|
||||
<p>To un-register, enable must be false.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
@ -131,9 +131,9 @@ void ConfigurationManager::setAccountDetails(const std::string& accountID, const
|
||||
Manager::instance().setAccountDetails(accountID, details);
|
||||
}
|
||||
|
||||
void ConfigurationManager::sendRegister(const std::string& accountID, const int32_t& expire)
|
||||
void ConfigurationManager::sendRegister(const std::string& accountID, const bool& enable)
|
||||
{
|
||||
Manager::instance().sendRegister(accountID, expire);
|
||||
Manager::instance().sendRegister(accountID, enable);
|
||||
}
|
||||
|
||||
std::string ConfigurationManager::addAccount(const std::map<std::string, std::string>& details)
|
||||
|
@ -68,7 +68,7 @@ class ConfigurationManager :
|
||||
void removeAccount(const std::string& accoundID);
|
||||
void deleteAllCredential(const std::string& accountID);
|
||||
std::vector< std::string > getAccountList();
|
||||
void sendRegister(const std::string& accoundID, const int32_t& expire);
|
||||
void sendRegister(const std::string& accoundID, const bool& enable);
|
||||
|
||||
std::map< std::string, std::string > getTlsSettingsDefault();
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <libgen.h>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace fileutils {
|
||||
static char *program_dir = NULL;
|
||||
|
||||
void set_program_dir(char *program_path)
|
||||
@ -42,3 +43,5 @@ const char *get_program_dir()
|
||||
{
|
||||
return program_dir;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,9 @@
|
||||
#ifndef __FILEUTILS_H__
|
||||
#define __FILEUTILS_H__
|
||||
|
||||
void set_program_dir(char *program_path);
|
||||
const char *get_program_dir();
|
||||
namespace fileutils {
|
||||
void set_program_dir(char *program_path);
|
||||
const char *get_program_dir();
|
||||
}
|
||||
|
||||
#endif // __FILEUTILS_H__
|
||||
|
@ -38,10 +38,9 @@
|
||||
#include "manager.h"
|
||||
|
||||
IAXAccount::IAXAccount(const std::string& accountID)
|
||||
: Account(accountID, "iax2"), password_()
|
||||
{
|
||||
link_ = new IAXVoIPLink(accountID);
|
||||
}
|
||||
: Account(accountID, "iax2"), password_(),
|
||||
link_(new IAXVoIPLink(accountID))
|
||||
{}
|
||||
|
||||
|
||||
IAXAccount::~IAXAccount()
|
||||
@ -160,7 +159,7 @@ IAXAccount::unregisterVoIPLink()
|
||||
{
|
||||
try {
|
||||
link_->sendUnregister(this);
|
||||
dynamic_cast<IAXVoIPLink*>(link_)->terminate();
|
||||
link_->terminate();
|
||||
} catch (const VoipLinkException &e) {
|
||||
ERROR("IAXAccount: %s", e.what());
|
||||
}
|
||||
@ -174,3 +173,8 @@ IAXAccount::loadConfig()
|
||||
enabled_ = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
VoIPLink* IAXAccount::getVoIPLink()
|
||||
{
|
||||
return link_;
|
||||
}
|
||||
|
@ -32,6 +32,9 @@
|
||||
#define IAXACCOUNT_H
|
||||
|
||||
#include "account.h"
|
||||
#include "noncopyable.h"
|
||||
|
||||
class IAXVoIPLink;
|
||||
|
||||
/**
|
||||
* @file: iaxaccount.h
|
||||
@ -64,8 +67,11 @@ class IAXAccount : public Account {
|
||||
}
|
||||
|
||||
private:
|
||||
NON_COPYABLE(IAXAccount);
|
||||
// Account login information: password
|
||||
std::string password_;
|
||||
IAXVoIPLink *link_;
|
||||
virtual VoIPLink* getVoIPLink();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@ static bool check_dir(const char *path)
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
set_program_dir(argv[0]);
|
||||
fileutils::set_program_dir(argv[0]);
|
||||
// makeCommandOptionParse allocates the object with operator new, so
|
||||
// auto_ptr is fine in this context.
|
||||
// TODO: This should eventually be replaced with std::unique_ptr for C++0x
|
||||
|
@ -410,10 +410,10 @@ class ManagerImpl {
|
||||
* ConfigurationManager - Send registration request
|
||||
* @param accountId The account to register/unregister
|
||||
* @param enable The flag for the type of registration
|
||||
* 0 for unregistration request
|
||||
* 1 for registration request
|
||||
* false for unregistration request
|
||||
* true for registration request
|
||||
*/
|
||||
void sendRegister(const std::string& accountId , const int32_t& enable);
|
||||
void sendRegister(const std::string& accountId, bool enable);
|
||||
|
||||
/**
|
||||
* Get account list
|
||||
|
@ -73,7 +73,7 @@ VoIPLink* ManagerImpl::getAccountLink(const std::string& accountID)
|
||||
|
||||
|
||||
void
|
||||
ManagerImpl::sendRegister(const std::string& accountID , const int32_t& enable)
|
||||
ManagerImpl::sendRegister(const std::string& accountID, bool enable)
|
||||
{
|
||||
Account* acc = getAccount(accountID);
|
||||
|
||||
|
@ -41,13 +41,17 @@
|
||||
const char * const SIPAccount::OVERRTP_STR = "overrtp";
|
||||
const char * const SIPAccount::SIPINFO_STR = "sipinfo";
|
||||
|
||||
namespace {
|
||||
const int MIN_REGISTRATION_TIME = 600;
|
||||
}
|
||||
|
||||
SIPAccount::SIPAccount(const std::string& accountID)
|
||||
: Account(accountID, "SIP")
|
||||
, transport_(NULL)
|
||||
, credentials_()
|
||||
, regc_(NULL)
|
||||
, bRegister_(false)
|
||||
, registrationExpire_(600)
|
||||
, registrationExpire_(MIN_REGISTRATION_TIME)
|
||||
, interface_("default")
|
||||
, publishedSameasLocal_(true)
|
||||
, publishedIpAddress_()
|
||||
@ -88,13 +92,12 @@ SIPAccount::SIPAccount(const std::string& accountID)
|
||||
, zrtpNotSuppWarning_(true)
|
||||
, registrationStateDetailed_()
|
||||
, keepAliveTimer_()
|
||||
{
|
||||
link_ = SIPVoIPLink::instance();
|
||||
}
|
||||
, link_(SIPVoIPLink::instance())
|
||||
{}
|
||||
|
||||
SIPAccount::~SIPAccount()
|
||||
{
|
||||
delete[] cred_;
|
||||
delete [] cred_;
|
||||
}
|
||||
|
||||
void SIPAccount::serialize(Conf::YamlEmitter *emitter)
|
||||
@ -111,9 +114,9 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter)
|
||||
ScalarNode hostname(Account::hostname_);
|
||||
ScalarNode enable(enabled_);
|
||||
ScalarNode type(Account::type_);
|
||||
std::stringstream expirevalstr;
|
||||
expirevalstr << registrationExpire_;
|
||||
ScalarNode expire(expirevalstr);
|
||||
std::stringstream registrationExpireStr;
|
||||
registrationExpireStr << registrationExpire_;
|
||||
ScalarNode expire(registrationExpireStr);
|
||||
ScalarNode interface(interface_);
|
||||
std::stringstream portstr;
|
||||
portstr << localPort_;
|
||||
@ -171,7 +174,7 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter)
|
||||
accountmap.setKeyValue(hostnameKey, &hostname);
|
||||
accountmap.setKeyValue(accountEnableKey, &enable);
|
||||
accountmap.setKeyValue(mailboxKey, &mailbox);
|
||||
accountmap.setKeyValue(expireKey, &expire);
|
||||
accountmap.setKeyValue(registrationExpireKey, &expire);
|
||||
accountmap.setKeyValue(interfaceKey, &interface);
|
||||
accountmap.setKeyValue(portKey, &port);
|
||||
accountmap.setKeyValue(stunServerKey, &stunServer);
|
||||
@ -244,7 +247,7 @@ void SIPAccount::serialize(Conf::YamlEmitter *emitter)
|
||||
delete node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SIPAccount::unserialize(Conf::MappingNode *map)
|
||||
@ -268,7 +271,7 @@ void SIPAccount::unserialize(Conf::MappingNode *map)
|
||||
|
||||
map->getValue(ringtonePathKey, &ringtonePath_);
|
||||
map->getValue(ringtoneEnabledKey, &ringtoneEnabled_);
|
||||
map->getValue(expireKey, ®istrationExpire_);
|
||||
map->getValue(registrationExpireKey, ®istrationExpire_);
|
||||
map->getValue(interfaceKey, &interface_);
|
||||
int port;
|
||||
map->getValue(portKey, &port);
|
||||
@ -404,7 +407,6 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
|
||||
stunServer_ = details[STUN_SERVER];
|
||||
stunEnabled_ = details[STUN_ENABLE] == "true";
|
||||
dtmfType_ = details[ACCOUNT_DTMF_TYPE];
|
||||
|
||||
registrationExpire_ = atoi(details[CONFIG_ACCOUNT_REGISTRATION_EXPIRE].c_str());
|
||||
|
||||
userAgent_ = details[USERAGENT];
|
||||
@ -488,9 +490,9 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const
|
||||
a[ROUTESET] = serviceRoute_;
|
||||
a[USERAGENT] = userAgent_;
|
||||
|
||||
std::stringstream expireval;
|
||||
expireval << registrationExpire_;
|
||||
a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = expireval.str();
|
||||
std::stringstream registrationExpireStr;
|
||||
registrationExpireStr << registrationExpire_;
|
||||
a[CONFIG_ACCOUNT_REGISTRATION_EXPIRE] = registrationExpireStr.str();
|
||||
a[LOCAL_INTERFACE] = interface_;
|
||||
a[PUBLISHED_SAMEAS_LOCAL] = publishedSameasLocal_ ? "true" : "false";
|
||||
a[PUBLISHED_ADDRESS] = publishedIpAddress_;
|
||||
@ -580,28 +582,27 @@ void SIPAccount::unregisterVoIPLink()
|
||||
}
|
||||
|
||||
void SIPAccount::startKeepAliveTimer() {
|
||||
pj_time_val keepAliveDelay_;
|
||||
|
||||
if (isTlsEnabled())
|
||||
return;
|
||||
|
||||
pj_time_val keepAliveDelay_;
|
||||
keepAliveTimer_.cb = &SIPAccount::keepAliveRegistrationCb;
|
||||
keepAliveTimer_.user_data = (void *)this;
|
||||
keepAliveTimer_.user_data = this;
|
||||
|
||||
// expiration may no be determined when during the first registration request
|
||||
if(registrationExpire_ == 0) {
|
||||
// expiration may be undetermined during the first registration request
|
||||
if (registrationExpire_ == 0)
|
||||
keepAliveDelay_.sec = 60;
|
||||
}
|
||||
else {
|
||||
else
|
||||
keepAliveDelay_.sec = registrationExpire_;
|
||||
}
|
||||
|
||||
keepAliveDelay_.msec = 0;
|
||||
|
||||
reinterpret_cast<SIPVoIPLink *>(link_)->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
|
||||
link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
|
||||
}
|
||||
|
||||
void SIPAccount::stopKeepAliveTimer() {
|
||||
reinterpret_cast<SIPVoIPLink *>(link_)->cancelKeepAliveTimer(keepAliveTimer_);
|
||||
link_->cancelKeepAliveTimer(keepAliveTimer_);
|
||||
}
|
||||
|
||||
pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum(const std::string& method)
|
||||
@ -669,7 +670,7 @@ void SIPAccount::initStunConfiguration()
|
||||
void SIPAccount::loadConfig()
|
||||
{
|
||||
if (registrationExpire_ == 0)
|
||||
registrationExpire_ = 600; /** Default expire value for registration */
|
||||
registrationExpire_ = MIN_REGISTRATION_TIME; /** Default expire value for registration */
|
||||
|
||||
if (tlsEnable_ == "true") {
|
||||
initTlsConfiguration();
|
||||
@ -794,8 +795,7 @@ std::string SIPAccount::getContactHeader() const
|
||||
|
||||
// Else we determine this infor based on transport information
|
||||
std::string address, port;
|
||||
SIPVoIPLink *siplink = dynamic_cast<SIPVoIPLink *>(link_);
|
||||
siplink->findLocalAddressFromTransport(transport_, transportType_, address, port);
|
||||
link_->findLocalAddressFromTransport(transport_, transportType_, address, port);
|
||||
|
||||
// UDP does not require the transport specification
|
||||
if (transportType_ == PJSIP_TRANSPORT_TLS) {
|
||||
@ -821,7 +821,7 @@ void SIPAccount::keepAliveRegistrationCb(UNUSED pj_timer_heap_t *th, pj_timer_en
|
||||
// send a new register request
|
||||
sipAccount->registerVoIPLink();
|
||||
|
||||
// make sure the current timer is deactivated
|
||||
// make sure the current timer is deactivated
|
||||
sipAccount->stopKeepAliveTimer();
|
||||
|
||||
// register a new timer
|
||||
@ -1036,3 +1036,8 @@ void SIPAccount::setTlsSettings(const std::map<std::string, std::string>& detail
|
||||
set_opt(details, TLS_NEGOTIATION_TIMEOUT_SEC, tlsNegotiationTimeoutSec_);
|
||||
set_opt(details, TLS_NEGOTIATION_TIMEOUT_MSEC, tlsNegotiationTimeoutMsec_);
|
||||
}
|
||||
|
||||
VoIPLink* SIPAccount::getVoIPLink()
|
||||
{
|
||||
return link_;
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ namespace Conf {
|
||||
class YamlEmitter;
|
||||
class MappingNode;
|
||||
// SIP specific configuration keys
|
||||
const char *const expireKey = "expire";
|
||||
const char *const interfaceKey = "interface";
|
||||
const char *const portKey = "port";
|
||||
const char *const publishAddrKey = "publishAddr";
|
||||
@ -114,6 +113,9 @@ class SIPAccount : public Account {
|
||||
* Virtual destructor
|
||||
*/
|
||||
virtual ~SIPAccount();
|
||||
|
||||
virtual VoIPLink* getVoIPLink();
|
||||
|
||||
std::string getUserAgentName() const;
|
||||
void setRegistrationStateDetailed(const std::pair<int, std::string> &details) {
|
||||
registrationStateDetailed_ = details;
|
||||
@ -224,7 +226,7 @@ class SIPAccount : public Account {
|
||||
* the "Expire" sip header or the CONTACT's "expire" param.
|
||||
*/
|
||||
void setRegistrationExpire(int expire) {
|
||||
if(expire > 0)
|
||||
if (expire > 0)
|
||||
registrationExpire_ = expire;
|
||||
}
|
||||
|
||||
@ -693,6 +695,11 @@ class SIPAccount : public Account {
|
||||
*/
|
||||
pj_timer_entry keepAliveTimer_;
|
||||
|
||||
|
||||
/**
|
||||
* Voice over IP Link contains a listener thread and calls
|
||||
*/
|
||||
SIPVoIPLink* link_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -94,7 +94,7 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP);
|
||||
/**
|
||||
* Helper function to parser header from incoming sip messages
|
||||
*/
|
||||
std::string fetchHeaderValue(pjsip_msg *msg, std::string field);
|
||||
std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field);
|
||||
|
||||
static pj_caching_pool pool_cache, *cp_ = &pool_cache;
|
||||
static pj_pool_t *pool_;
|
||||
@ -102,17 +102,17 @@ static pjsip_endpoint *endpt_;
|
||||
static pjsip_module mod_ua_;
|
||||
static pj_thread_t *thread;
|
||||
|
||||
static void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status UNUSED);
|
||||
static void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer);
|
||||
static void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer);
|
||||
static void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e);
|
||||
static void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e);
|
||||
static void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
|
||||
static void registration_cb(pjsip_regc_cbparam *param);
|
||||
static pj_bool_t transaction_request_cb(pjsip_rx_data *rdata);
|
||||
static pj_bool_t transaction_response_cb(pjsip_rx_data *rdata UNUSED) ;
|
||||
void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status UNUSED);
|
||||
void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer);
|
||||
void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer);
|
||||
void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *e);
|
||||
void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e);
|
||||
void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
|
||||
void registration_cb(pjsip_regc_cbparam *param);
|
||||
pj_bool_t transaction_request_cb(pjsip_rx_data *rdata);
|
||||
pj_bool_t transaction_response_cb(pjsip_rx_data *rdata UNUSED) ;
|
||||
|
||||
static void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event);
|
||||
void transfer_client_cb(pjsip_evsub *sub, pjsip_event *event);
|
||||
|
||||
/**
|
||||
* Send a reINVITE inside an active dialog to modify its state
|
||||
@ -163,6 +163,274 @@ pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
|
||||
return route_set;
|
||||
}
|
||||
|
||||
void handleIncomingOptions(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_tx_data *tdata;
|
||||
|
||||
if (pjsip_endpt_create_response(endpt_, rdata, PJSIP_SC_OK, NULL, &tdata) != PJ_SUCCESS)
|
||||
return;
|
||||
|
||||
#define ADD_HDR(hdr) do { \
|
||||
const pjsip_hdr *cap_hdr = hdr; \
|
||||
if (cap_hdr) \
|
||||
pjsip_msg_add_hdr (tdata->msg, (pjsip_hdr*) pjsip_hdr_clone (tdata->pool, cap_hdr)); \
|
||||
} while(0)
|
||||
#define ADD_CAP(cap) ADD_HDR(pjsip_endpt_get_capability(endpt_, cap, NULL));
|
||||
|
||||
ADD_CAP(PJSIP_H_ALLOW);
|
||||
ADD_CAP(PJSIP_H_ACCEPT);
|
||||
ADD_CAP(PJSIP_H_SUPPORTED);
|
||||
ADD_HDR(pjsip_evsub_get_allow_events_hdr(NULL));
|
||||
|
||||
pjsip_response_addr res_addr;
|
||||
pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
|
||||
|
||||
if (pjsip_endpt_send_response(endpt_, &res_addr, tdata, NULL, NULL) != PJ_SUCCESS)
|
||||
pjsip_tx_data_dec_ref(tdata);
|
||||
}
|
||||
|
||||
pj_bool_t transaction_response_cb(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
|
||||
|
||||
if (!dlg)
|
||||
return PJ_SUCCESS;
|
||||
|
||||
pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
|
||||
|
||||
if (!tsx or tsx->method.id != PJSIP_INVITE_METHOD)
|
||||
return PJ_SUCCESS;
|
||||
|
||||
if (tsx->status_code / 100 == 2) {
|
||||
/**
|
||||
* Send an ACK message inside a transaction. PJSIP send automatically, non-2xx ACK response.
|
||||
* ACK for a 2xx response must be send using this method.
|
||||
*/
|
||||
pjsip_tx_data *tdata;
|
||||
pjsip_dlg_create_request(dlg, &pjsip_ack_method, rdata->msg_info.cseq->cseq, &tdata);
|
||||
pjsip_dlg_send_request(dlg, tdata, -1, NULL);
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
std::string parseDisplayName(const char * buffer)
|
||||
{
|
||||
const char* from_header = strstr(buffer, "From: ");
|
||||
|
||||
if (!from_header)
|
||||
return "";
|
||||
|
||||
std::string temp(from_header);
|
||||
size_t begin_displayName = temp.find("\"") + 1;
|
||||
size_t end_displayName = temp.rfind("\"");
|
||||
std::string displayName(temp.substr(begin_displayName, end_displayName - begin_displayName));
|
||||
|
||||
static const size_t MAX_DISPLAY_NAME_SIZE = 25;
|
||||
if (displayName.size() > MAX_DISPLAY_NAME_SIZE)
|
||||
return "";
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
void stripSipUriPrefix(std::string& sipUri)
|
||||
{
|
||||
// Remove sip: prefix
|
||||
static const char SIP_PREFIX[] = "sip:";
|
||||
size_t found = sipUri.find(SIP_PREFIX);
|
||||
|
||||
if (found != std::string::npos)
|
||||
sipUri.erase(found, found + (sizeof SIP_PREFIX) - 1);
|
||||
|
||||
found = sipUri.find("@");
|
||||
|
||||
if (found != std::string::npos)
|
||||
sipUri.erase(found);
|
||||
}
|
||||
|
||||
pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_method *method = &rdata->msg_info.msg->line.req.method;
|
||||
|
||||
if (method->id == PJSIP_ACK_METHOD && pjsip_rdata_get_dlg(rdata))
|
||||
return true;
|
||||
|
||||
pjsip_sip_uri *sip_to_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.to->uri);
|
||||
pjsip_sip_uri *sip_from_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.from->uri);
|
||||
std::string userName(sip_to_uri->user.ptr, sip_to_uri->user.slen);
|
||||
std::string server(sip_from_uri->host.ptr, sip_from_uri->host.slen);
|
||||
std::string account_id(Manager::instance().getAccountIdFromNameAndServer(userName, server));
|
||||
|
||||
std::string displayName(parseDisplayName(rdata->msg_info.msg_buf));
|
||||
|
||||
if (method->id == PJSIP_OTHER_METHOD) {
|
||||
pj_str_t *str = &method->name;
|
||||
std::string request(str->ptr, str->slen);
|
||||
|
||||
if (request.find("NOTIFY") != (size_t)-1) {
|
||||
int voicemail;
|
||||
|
||||
if (sscanf((const char*)rdata->msg_info.msg->body->data, "Voice-Message: %d/", &voicemail) == 1 && voicemail != 0)
|
||||
Manager::instance().startVoiceMessageNotification(account_id, voicemail);
|
||||
}
|
||||
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_OK, NULL, NULL, NULL);
|
||||
|
||||
return true;
|
||||
} else if (method->id == PJSIP_OPTIONS_METHOD) {
|
||||
handleIncomingOptions(rdata);
|
||||
return true;
|
||||
} else if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_METHOD_NOT_ALLOWED, NULL, NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(account_id));
|
||||
|
||||
pjmedia_sdp_session *r_sdp;
|
||||
pjsip_msg_body *body = rdata->msg_info.msg->body;
|
||||
|
||||
if (!body || pjmedia_sdp_parse(rdata->tp_info.pool, (char*) body->data, body->len, &r_sdp) != PJ_SUCCESS)
|
||||
r_sdp = NULL;
|
||||
|
||||
if (account->getActiveCodecs().empty()) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata,
|
||||
PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that we can handle the request
|
||||
unsigned options = 0;
|
||||
|
||||
if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, endpt_, NULL) != PJ_SUCCESS) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_METHOD_NOT_ALLOWED, NULL, NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Manager::instance().hookPreference.getSipEnabled()) {
|
||||
std::string header_value(fetchHeaderValue(rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField()));
|
||||
UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), header_value);
|
||||
}
|
||||
|
||||
SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_);
|
||||
Manager::instance().associateCallToAccount(call->getCallId(), account_id);
|
||||
|
||||
// May use the published address as well
|
||||
std::string addrToUse = SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface());
|
||||
std::string addrSdp = account->isStunEnabled()
|
||||
? account->getPublishedAddress()
|
||||
: addrToUse;
|
||||
|
||||
pjsip_tpselector *tp = SIPVoIPLink::instance()->initTransportSelector(account->transport_, call->getMemoryPool());
|
||||
|
||||
if (addrToUse == "0.0.0.0")
|
||||
addrToUse = getSIPLocalIP();
|
||||
|
||||
if (addrSdp == "0.0.0.0")
|
||||
addrSdp = addrToUse;
|
||||
|
||||
char tmp[PJSIP_MAX_URL_SIZE];
|
||||
int length = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_from_uri, tmp, PJSIP_MAX_URL_SIZE);
|
||||
std::string peerNumber(tmp, length);
|
||||
stripSipUriPrefix(peerNumber);
|
||||
|
||||
call->setConnectionState(Call::PROGRESSING);
|
||||
call->setPeerNumber(peerNumber);
|
||||
call->setDisplayName(displayName);
|
||||
call->initRecFilename(peerNumber);
|
||||
|
||||
setCallMediaLocal(call, addrToUse);
|
||||
|
||||
call->getLocalSDP()->setLocalIP(addrSdp);
|
||||
|
||||
call->getAudioRtp().initAudioRtpConfig();
|
||||
call->getAudioRtp().initAudioSymmetricRtpSession();
|
||||
|
||||
if (rdata->msg_info.msg->body) {
|
||||
char sdpbuffer[1000];
|
||||
int len = rdata->msg_info.msg->body->print_body(rdata->msg_info.msg->body, sdpbuffer, sizeof sdpbuffer);
|
||||
|
||||
if (len == -1) // error
|
||||
len = 0;
|
||||
|
||||
std::string sdpoffer(sdpbuffer, len);
|
||||
size_t start = sdpoffer.find("a=crypto:");
|
||||
|
||||
// Found crypto header in SDP
|
||||
if (start != std::string::npos) {
|
||||
CryptoOffer crypto_offer;
|
||||
crypto_offer.push_back(std::string(sdpoffer.substr(start, (sdpoffer.size() - start) - 1)));
|
||||
|
||||
std::vector<sfl::CryptoSuiteDefinition>localCapabilities;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
localCapabilities.push_back(sfl::CryptoSuites[i]);
|
||||
|
||||
sfl::SdesNegotiator sdesnego(localCapabilities, crypto_offer);
|
||||
|
||||
if (sdesnego.negotiate()) {
|
||||
call->getAudioRtp().setRemoteCryptoInfo(sdesnego);
|
||||
call->getAudioRtp().initLocalCryptoInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call->getLocalSDP()->receiveOffer(r_sdp, account->getActiveCodecs());
|
||||
|
||||
sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW);
|
||||
call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec));
|
||||
|
||||
pjsip_dialog* dialog;
|
||||
|
||||
if (pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, NULL, &dialog) != PJ_SUCCESS) {
|
||||
delete call;
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
pjsip_inv_create_uas(dialog, rdata, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv);
|
||||
|
||||
PJ_ASSERT_RETURN(pjsip_dlg_set_transport(dialog, tp) == PJ_SUCCESS, 1);
|
||||
|
||||
call->inv->mod_data[mod_ua_.id] = call;
|
||||
|
||||
// Check whether Replaces header is present in the request and process accordingly.
|
||||
pjsip_dialog *replaced_dlg;
|
||||
pjsip_tx_data *response;
|
||||
|
||||
if (pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE, &response) != PJ_SUCCESS) {
|
||||
ERROR("Something wrong with Replaces request.");
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, 500 /* internal server error */, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// Check if call has been transfered
|
||||
pjsip_tx_data *tdata;
|
||||
|
||||
if (replaced_dlg) { // If Replace header present
|
||||
// Always answer the new INVITE with 200, regardless whether
|
||||
// the replaced call is in early or confirmed state.
|
||||
if (pjsip_inv_answer(call->inv, 200, NULL, NULL, &response) == PJ_SUCCESS)
|
||||
pjsip_inv_send_msg(call->inv, response);
|
||||
|
||||
// Get the INVITE session associated with the replaced dialog.
|
||||
pjsip_inv_session *replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
|
||||
|
||||
// Disconnect the "replaced" INVITE session.
|
||||
if (pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, &tdata) == PJ_SUCCESS && tdata)
|
||||
pjsip_inv_send_msg(replaced_inv, tdata);
|
||||
} else { // Prooceed with normal call flow
|
||||
PJ_ASSERT_RETURN(pjsip_inv_initial_answer(call->inv, rdata, PJSIP_SC_RINGING, NULL, NULL, &tdata) == PJ_SUCCESS, 1);
|
||||
PJ_ASSERT_RETURN(pjsip_inv_send_msg(call->inv, tdata) == PJ_SUCCESS, 1);
|
||||
|
||||
call->setConnectionState(Call::RINGING);
|
||||
|
||||
Manager::instance().incomingCall(call, account_id);
|
||||
Manager::instance().getAccountLink(account_id)->addCall(call);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
/*************************************************************************************************/
|
||||
@ -170,9 +438,9 @@ pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
|
||||
SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this))
|
||||
{
|
||||
#define TRY(ret) do { \
|
||||
if (ret != PJ_SUCCESS) \
|
||||
throw VoipLinkException(#ret " failed"); \
|
||||
} while(0)
|
||||
if (ret != PJ_SUCCESS) \
|
||||
throw VoipLinkException(#ret " failed"); \
|
||||
} while(0)
|
||||
|
||||
srand(time(NULL)); // to get random number for RANDOM_PORT
|
||||
|
||||
@ -389,9 +657,8 @@ void SIPVoIPLink::registerKeepAliveTimer(pj_timer_entry& timer, pj_time_val& del
|
||||
pj_status_t status;
|
||||
|
||||
status = pjsip_endpt_schedule_timer(endpt_, &timer, &delay);
|
||||
if(status != PJ_SUCCESS) {
|
||||
if (status != PJ_SUCCESS)
|
||||
ERROR("Could not schedule new timer in pjsip endpoint");
|
||||
}
|
||||
}
|
||||
|
||||
void SIPVoIPLink::cancelKeepAliveTimer(pj_timer_entry& timer)
|
||||
@ -975,12 +1242,12 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to)
|
||||
// Private functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static pj_bool_t stun_sock_on_status_cb(pj_stun_sock *stun_sock UNUSED, pj_stun_sock_op op UNUSED, pj_status_t status)
|
||||
pj_bool_t stun_sock_on_status_cb(pj_stun_sock *stun_sock UNUSED, pj_stun_sock_op op UNUSED, pj_status_t status)
|
||||
{
|
||||
return status == PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static pj_bool_t stun_sock_on_rx_data_cb(pj_stun_sock *stun_sock UNUSED, void *pkt UNUSED, unsigned pkt_len UNUSED, const pj_sockaddr_t *src_addr UNUSED, unsigned addr_len UNUSED)
|
||||
pj_bool_t stun_sock_on_rx_data_cb(pj_stun_sock *stun_sock UNUSED, void *pkt UNUSED, unsigned pkt_len UNUSED, const pj_sockaddr_t *src_addr UNUSED, unsigned addr_len UNUSED)
|
||||
{
|
||||
return PJ_TRUE;
|
||||
}
|
||||
@ -1223,7 +1490,7 @@ void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsi
|
||||
addr = std::string(pjMachineName->ptr, pjMachineName->slen);
|
||||
|
||||
// Update address and port with active transport
|
||||
if(!transport) {
|
||||
if (!transport) {
|
||||
ERROR("SIPVoIPLink: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str());
|
||||
return;
|
||||
}
|
||||
@ -1239,11 +1506,10 @@ void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsi
|
||||
// TODO Need to determine why we exclude TLS here...
|
||||
// if (transportType == PJSIP_TRANSPORT_UDP and transport_)
|
||||
pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_);
|
||||
if(!tp_sel) {
|
||||
if (!tp_sel) {
|
||||
ERROR("SIPVoIPLink: Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
pj_str_t localAddress = {0,0};
|
||||
int i_port = 0;
|
||||
@ -1268,40 +1534,6 @@ void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsi
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string parseDisplayName(const char * buffer)
|
||||
{
|
||||
const char* from_header = strstr(buffer, "From: ");
|
||||
|
||||
if (!from_header)
|
||||
return "";
|
||||
|
||||
std::string temp(from_header);
|
||||
size_t begin_displayName = temp.find("\"") + 1;
|
||||
size_t end_displayName = temp.rfind("\"");
|
||||
std::string displayName(temp.substr(begin_displayName, end_displayName - begin_displayName));
|
||||
|
||||
static const size_t MAX_DISPLAY_NAME_SIZE = 25;
|
||||
if (displayName.size() > MAX_DISPLAY_NAME_SIZE)
|
||||
return "";
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
void stripSipUriPrefix(std::string& sipUri)
|
||||
{
|
||||
// Remove sip: prefix
|
||||
static const char SIP_PREFIX[] = "sip:";
|
||||
size_t found = sipUri.find(SIP_PREFIX);
|
||||
|
||||
if (found != std::string::npos)
|
||||
sipUri.erase(found, found + (sizeof SIP_PREFIX) - 1);
|
||||
|
||||
found = sipUri.find("@");
|
||||
|
||||
if (found != std::string::npos)
|
||||
sipUri.erase(found);
|
||||
}
|
||||
|
||||
int SIPSessionReinvite(SIPCall *call)
|
||||
{
|
||||
pjsip_tx_data *tdata;
|
||||
@ -1386,7 +1618,7 @@ void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *off
|
||||
pjsip_inv_set_sdp_answer(call->inv, call->getLocalSDP()->getLocalSdpSession());
|
||||
}
|
||||
|
||||
static void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
|
||||
void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
|
||||
{
|
||||
SIPCall *call = reinterpret_cast<SIPCall*>(inv->mod_data[mod_ua_.id]);
|
||||
std::string accountid(Manager::instance().getAccountFromCall(call->getCallId()));
|
||||
@ -1612,11 +1844,8 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti
|
||||
}
|
||||
}
|
||||
|
||||
static void update_contact_header(struct pjsip_regc_cbparam *param, SIPAccount *account)
|
||||
void update_contact_header(struct pjsip_regc_cbparam *param, SIPAccount *account)
|
||||
{
|
||||
pj_pool_t *pool = NULL;
|
||||
pjsip_contact_hdr *contact_hdr = NULL;
|
||||
pjsip_sip_uri *uri = NULL;
|
||||
|
||||
SIPVoIPLink *siplink = dynamic_cast<SIPVoIPLink *>(account->getVoIPLink());
|
||||
if(siplink == NULL) {
|
||||
@ -1624,39 +1853,36 @@ static void update_contact_header(struct pjsip_regc_cbparam *param, SIPAccount *
|
||||
return;
|
||||
}
|
||||
|
||||
pool = pj_pool_create(&cp_->factory, "tmp", 512, 512, NULL);
|
||||
pj_pool_t *pool = pj_pool_create(&cp_->factory, "tmp", 512, 512, NULL);
|
||||
if(pool == NULL) {
|
||||
ERROR("SIPVoIPLink: Could not create temporary memory pool in transport header");
|
||||
return;
|
||||
}
|
||||
|
||||
if(param->contact_cnt == 0) {
|
||||
if (param->contact_cnt == 0) {
|
||||
WARN("SIPVoIPLink: No contact header in registration callback");
|
||||
pj_pool_release(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
contact_hdr = param->contact[0];
|
||||
pjsip_contact_hdr *contact_hdr = param->contact[0];
|
||||
|
||||
uri = (pjsip_sip_uri*) contact_hdr->uri;
|
||||
if(uri == NULL) {
|
||||
pjsip_sip_uri *uri = (pjsip_sip_uri*) contact_hdr->uri;
|
||||
if (uri == NULL) {
|
||||
ERROR("SIPVoIPLink: Could not find uri in contact header");
|
||||
pj_pool_release(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri);
|
||||
|
||||
if (uri->port == 0) {
|
||||
// TODO: make this base on transport type
|
||||
uri->port = 5060; //pjsip_transport_get_default_port_for_type(tp_type);
|
||||
}
|
||||
// TODO: make this based on transport type
|
||||
// with pjsip_transport_get_default_port_for_type(tp_type);
|
||||
if (uri->port == 0)
|
||||
uri->port = DEFAULT_SIP_PORT;
|
||||
|
||||
std::string recvContactHost(uri->host.ptr, uri->host.slen);
|
||||
std::stringstream ss;
|
||||
ss << uri->port;
|
||||
std::string recvContactPort = ss.str();
|
||||
|
||||
|
||||
std::string currentAddress, currentPort;
|
||||
siplink->findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort);
|
||||
@ -1679,7 +1905,6 @@ static void update_contact_header(struct pjsip_regc_cbparam *param, SIPAccount *
|
||||
account->setContactHeader(recvContactHost, recvContactPort);
|
||||
siplink->sendRegister(account);
|
||||
}
|
||||
|
||||
pj_pool_release(pool);
|
||||
}
|
||||
|
||||
@ -1763,243 +1988,6 @@ void registration_cb(struct pjsip_regc_cbparam *param)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void handleIncomingOptions(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_tx_data *tdata;
|
||||
|
||||
if (pjsip_endpt_create_response(endpt_, rdata, PJSIP_SC_OK, NULL, &tdata) != PJ_SUCCESS)
|
||||
return;
|
||||
|
||||
#define ADD_HDR(hdr) do { \
|
||||
const pjsip_hdr *cap_hdr = hdr; \
|
||||
if (cap_hdr) \
|
||||
pjsip_msg_add_hdr (tdata->msg, (pjsip_hdr*) pjsip_hdr_clone (tdata->pool, cap_hdr)); \
|
||||
} while(0)
|
||||
#define ADD_CAP(cap) ADD_HDR(pjsip_endpt_get_capability(endpt_, cap, NULL));
|
||||
|
||||
ADD_CAP(PJSIP_H_ALLOW);
|
||||
ADD_CAP(PJSIP_H_ACCEPT);
|
||||
ADD_CAP(PJSIP_H_SUPPORTED);
|
||||
ADD_HDR(pjsip_evsub_get_allow_events_hdr(NULL));
|
||||
|
||||
pjsip_response_addr res_addr;
|
||||
pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
|
||||
|
||||
if (pjsip_endpt_send_response(endpt_, &res_addr, tdata, NULL, NULL) != PJ_SUCCESS)
|
||||
pjsip_tx_data_dec_ref(tdata);
|
||||
}
|
||||
|
||||
|
||||
static pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_method *method = &rdata->msg_info.msg->line.req.method;
|
||||
|
||||
if (method->id == PJSIP_ACK_METHOD && pjsip_rdata_get_dlg(rdata))
|
||||
return true;
|
||||
|
||||
pjsip_sip_uri *sip_to_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.to->uri);
|
||||
pjsip_sip_uri *sip_from_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.from->uri);
|
||||
std::string userName(sip_to_uri->user.ptr, sip_to_uri->user.slen);
|
||||
std::string server(sip_from_uri->host.ptr, sip_from_uri->host.slen);
|
||||
std::string account_id(Manager::instance().getAccountIdFromNameAndServer(userName, server));
|
||||
|
||||
std::string displayName(parseDisplayName(rdata->msg_info.msg_buf));
|
||||
|
||||
if (method->id == PJSIP_OTHER_METHOD) {
|
||||
pj_str_t *str = &method->name;
|
||||
std::string request(str->ptr, str->slen);
|
||||
|
||||
if (request.find("NOTIFY") != (size_t)-1) {
|
||||
int voicemail;
|
||||
|
||||
if (sscanf((const char*)rdata->msg_info.msg->body->data, "Voice-Message: %d/", &voicemail) == 1 && voicemail != 0)
|
||||
Manager::instance().startVoiceMessageNotification(account_id, voicemail);
|
||||
}
|
||||
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_OK, NULL, NULL, NULL);
|
||||
|
||||
return true;
|
||||
} else if (method->id == PJSIP_OPTIONS_METHOD) {
|
||||
handleIncomingOptions(rdata);
|
||||
return true;
|
||||
} else if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_METHOD_NOT_ALLOWED, NULL, NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(account_id));
|
||||
|
||||
pjmedia_sdp_session *r_sdp;
|
||||
pjsip_msg_body *body = rdata->msg_info.msg->body;
|
||||
|
||||
if (!body || pjmedia_sdp_parse(rdata->tp_info.pool, (char*) body->data, body->len, &r_sdp) != PJ_SUCCESS)
|
||||
r_sdp = NULL;
|
||||
|
||||
if (account->getActiveCodecs().empty()) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata,
|
||||
PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL,
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that we can handle the request
|
||||
unsigned options = 0;
|
||||
|
||||
if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, endpt_, NULL) != PJ_SUCCESS) {
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_METHOD_NOT_ALLOWED, NULL, NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Manager::instance().hookPreference.getSipEnabled()) {
|
||||
std::string header_value(fetchHeaderValue(rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField()));
|
||||
UrlHook::runAction(Manager::instance().hookPreference.getUrlCommand(), header_value);
|
||||
}
|
||||
|
||||
SIPCall* call = new SIPCall(Manager::instance().getNewCallID(), Call::INCOMING, cp_);
|
||||
Manager::instance().associateCallToAccount(call->getCallId(), account_id);
|
||||
|
||||
// May use the published address as well
|
||||
std::string addrToUse = SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface());
|
||||
std::string addrSdp = account->isStunEnabled()
|
||||
? account->getPublishedAddress()
|
||||
: addrToUse;
|
||||
|
||||
pjsip_tpselector *tp = SIPVoIPLink::instance()->initTransportSelector(account->transport_, call->getMemoryPool());
|
||||
|
||||
if (addrToUse == "0.0.0.0")
|
||||
addrToUse = getSIPLocalIP();
|
||||
|
||||
if (addrSdp == "0.0.0.0")
|
||||
addrSdp = addrToUse;
|
||||
|
||||
char tmp[PJSIP_MAX_URL_SIZE];
|
||||
int length = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_from_uri, tmp, PJSIP_MAX_URL_SIZE);
|
||||
std::string peerNumber(tmp, length);
|
||||
stripSipUriPrefix(peerNumber);
|
||||
|
||||
call->setConnectionState(Call::PROGRESSING);
|
||||
call->setPeerNumber(peerNumber);
|
||||
call->setDisplayName(displayName);
|
||||
call->initRecFilename(peerNumber);
|
||||
|
||||
setCallMediaLocal(call, addrToUse);
|
||||
|
||||
call->getLocalSDP()->setLocalIP(addrSdp);
|
||||
|
||||
call->getAudioRtp().initAudioRtpConfig();
|
||||
call->getAudioRtp().initAudioSymmetricRtpSession();
|
||||
|
||||
if (rdata->msg_info.msg->body) {
|
||||
char sdpbuffer[1000];
|
||||
int len = rdata->msg_info.msg->body->print_body(rdata->msg_info.msg->body, sdpbuffer, sizeof sdpbuffer);
|
||||
|
||||
if (len == -1) // error
|
||||
len = 0;
|
||||
|
||||
std::string sdpoffer(sdpbuffer, len);
|
||||
size_t start = sdpoffer.find("a=crypto:");
|
||||
|
||||
// Found crypto header in SDP
|
||||
if (start != std::string::npos) {
|
||||
CryptoOffer crypto_offer;
|
||||
crypto_offer.push_back(std::string(sdpoffer.substr(start, (sdpoffer.size() - start) - 1)));
|
||||
|
||||
std::vector<sfl::CryptoSuiteDefinition>localCapabilities;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
localCapabilities.push_back(sfl::CryptoSuites[i]);
|
||||
|
||||
sfl::SdesNegotiator sdesnego(localCapabilities, crypto_offer);
|
||||
|
||||
if (sdesnego.negotiate()) {
|
||||
call->getAudioRtp().setRemoteCryptoInfo(sdesnego);
|
||||
call->getAudioRtp().initLocalCryptoInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call->getLocalSDP()->receiveOffer(r_sdp, account->getActiveCodecs());
|
||||
|
||||
sfl::Codec* audiocodec = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW);
|
||||
call->getAudioRtp().start(static_cast<sfl::AudioCodec *>(audiocodec));
|
||||
|
||||
pjsip_dialog* dialog;
|
||||
|
||||
if (pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, NULL, &dialog) != PJ_SUCCESS) {
|
||||
delete call;
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, PJSIP_SC_INTERNAL_SERVER_ERROR, NULL, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
pjsip_inv_create_uas(dialog, rdata, call->getLocalSDP()->getLocalSdpSession(), 0, &call->inv);
|
||||
|
||||
PJ_ASSERT_RETURN(pjsip_dlg_set_transport(dialog, tp) == PJ_SUCCESS, 1);
|
||||
|
||||
call->inv->mod_data[mod_ua_.id] = call;
|
||||
|
||||
// Check whether Replaces header is present in the request and process accordingly.
|
||||
pjsip_dialog *replaced_dlg;
|
||||
pjsip_tx_data *response;
|
||||
|
||||
if (pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE, &response) != PJ_SUCCESS) {
|
||||
ERROR("Something wrong with Replaces request.");
|
||||
pjsip_endpt_respond_stateless(endpt_, rdata, 500 /* internal server error */, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// Check if call has been transfered
|
||||
pjsip_tx_data *tdata;
|
||||
|
||||
if (replaced_dlg) { // If Replace header present
|
||||
// Always answer the new INVITE with 200, regardless whether
|
||||
// the replaced call is in early or confirmed state.
|
||||
if (pjsip_inv_answer(call->inv, 200, NULL, NULL, &response) == PJ_SUCCESS)
|
||||
pjsip_inv_send_msg(call->inv, response);
|
||||
|
||||
// Get the INVITE session associated with the replaced dialog.
|
||||
pjsip_inv_session *replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
|
||||
|
||||
// Disconnect the "replaced" INVITE session.
|
||||
if (pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, &tdata) == PJ_SUCCESS && tdata)
|
||||
pjsip_inv_send_msg(replaced_inv, tdata);
|
||||
} else { // Prooceed with normal call flow
|
||||
PJ_ASSERT_RETURN(pjsip_inv_initial_answer(call->inv, rdata, PJSIP_SC_RINGING, NULL, NULL, &tdata) == PJ_SUCCESS, 1);
|
||||
PJ_ASSERT_RETURN(pjsip_inv_send_msg(call->inv, tdata) == PJ_SUCCESS, 1);
|
||||
|
||||
call->setConnectionState(Call::RINGING);
|
||||
|
||||
Manager::instance().incomingCall(call, account_id);
|
||||
Manager::instance().getAccountLink(account_id)->addCall(call);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static pj_bool_t transaction_response_cb(pjsip_rx_data *rdata)
|
||||
{
|
||||
pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
|
||||
|
||||
if (!dlg)
|
||||
return PJ_SUCCESS;
|
||||
|
||||
pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
|
||||
|
||||
if (!tsx or tsx->method.id != PJSIP_INVITE_METHOD)
|
||||
return PJ_SUCCESS;
|
||||
|
||||
if (tsx->status_code / 100 == 2) {
|
||||
/**
|
||||
* Send an ACK message inside a transaction. PJSIP send automatically, non-2xx ACK response.
|
||||
* ACK for a 2xx response must be send using this method.
|
||||
*/
|
||||
pjsip_tx_data *tdata;
|
||||
pjsip_dlg_create_request(dlg, &pjsip_ack_method, rdata->msg_info.cseq->cseq, &tdata);
|
||||
pjsip_dlg_send_request(dlg, tdata, -1, NULL);
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata)
|
||||
{
|
||||
SIPCall *currentCall = reinterpret_cast<SIPCall *>(inv->mod_data[mod_ua_.id]);
|
||||
@ -2101,7 +2089,7 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP)
|
||||
call->getLocalSDP()->setLocalPublishedAudioPort(callLocalExternAudioPort);
|
||||
}
|
||||
|
||||
std::string fetchHeaderValue(pjsip_msg *msg, std::string field)
|
||||
std::string fetchHeaderValue(pjsip_msg *msg, const std::string &field)
|
||||
{
|
||||
pj_str_t name = pj_str((char*) field.c_str());
|
||||
|
||||
@ -2119,7 +2107,6 @@ std::string fetchHeaderValue(pjsip_msg *msg, std::string field)
|
||||
|
||||
return value.substr(0, pos);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
std::vector<std::string> SIPVoIPLink::getAllIpInterfaceByName()
|
||||
|
@ -166,7 +166,7 @@ void ConfigurationTest::testYamlEmitter()
|
||||
accountmap.setKeyValue(hostnameKey, &hostname);
|
||||
accountmap.setKeyValue(accountEnableKey, &enable);
|
||||
accountmap.setKeyValue(mailboxKey, &mailbox);
|
||||
accountmap.setKeyValue(expireKey, &expire);
|
||||
accountmap.setKeyValue(registrationExpireKey, &expire);
|
||||
accountmap.setKeyValue(interfaceKey, &interface);
|
||||
accountmap.setKeyValue(portKey, &port);
|
||||
accountmap.setKeyValue(publishAddrKey, &publishAddr);
|
||||
|
@ -260,17 +260,15 @@ static void enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path,
|
||||
// Modify account state
|
||||
gchar * registrationState;
|
||||
|
||||
if (enable == TRUE) {
|
||||
if (enable == TRUE)
|
||||
registrationState = g_strdup("true");
|
||||
} else {
|
||||
else
|
||||
registrationState = g_strdup("false");
|
||||
}
|
||||
|
||||
DEBUG("Replacing with %s", registrationState);
|
||||
g_hash_table_replace(acc->properties , g_strdup(ACCOUNT_ENABLED), registrationState);
|
||||
|
||||
dbus_send_register(acc->accountID, enable);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1518,7 +1518,7 @@ static void menuitem_response(gchar *string)
|
||||
dbus_join_participant(calltree_selected_call->_callID,
|
||||
calltree_dragged_call->_callID);
|
||||
else if (g_strcmp0(string, SFL_TRANSFER_CALL) == 0) {
|
||||
DEBUG("Calltree: Transfering call %s, to %s",
|
||||
DEBUG("Calltree: Transferring call %s, to %s",
|
||||
calltree_selected_call->_peer_number,
|
||||
calltree_dragged_call->_peer_number);
|
||||
dbus_attended_transfer(calltree_selected_call, calltree_dragged_call);
|
||||
|
@ -190,7 +190,7 @@
|
||||
<tp:docstring>
|
||||
Send account registration (REGISTER) to the registrar.
|
||||
</tp:docstring>
|
||||
the account if expire=1, unregister if expire=0.
|
||||
Register the account if enable=true, unregister if enable=false.
|
||||
|
||||
@param[in] input accountID
|
||||
-->
|
||||
@ -199,10 +199,10 @@
|
||||
The account ID
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="i" name="expire" direction="in">
|
||||
<arg type="b" name="enable" direction="in">
|
||||
<tp:docstring>
|
||||
<p>To register, expire must be 1.</p>
|
||||
<p>To un-register, expire must be 0.</p>
|
||||
<p>To register, enable must be true.</p>
|
||||
<p>To un-register, enable must be false.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
@ -1030,7 +1030,7 @@ dbus_get_ip2_ip_details(void)
|
||||
}
|
||||
|
||||
void
|
||||
dbus_send_register(gchar* accountID, const guint enable)
|
||||
dbus_send_register(gchar* accountID, gboolean enable)
|
||||
{
|
||||
GError *error = NULL;
|
||||
org_sflphone_SFLphone_ConfigurationManager_send_register(
|
||||
|
@ -155,7 +155,7 @@ GHashTable * dbus_get_ip2_ip_details (void);
|
||||
* 0 for unregistration request
|
||||
* 1 for registration request
|
||||
*/
|
||||
void dbus_send_register (gchar* accountID , const guint enable);
|
||||
void dbus_send_register (gchar* accountID, gboolean enable);
|
||||
|
||||
/**
|
||||
* ConfigurationManager - Add an account to the list
|
||||
|
@ -690,7 +690,7 @@ void SFLPhoneView::transfer()
|
||||
{
|
||||
Call* call = callTreeModel->getCurrentItem();
|
||||
if(!call) {
|
||||
kDebug() << "Error : Transfering when no item selected. Should not happen.";
|
||||
kDebug() << "Error : Transferring when no item selected. Should not happen.";
|
||||
}
|
||||
else {
|
||||
action(call, CALL_ACTION_TRANSFER);
|
||||
|
@ -190,7 +190,7 @@
|
||||
<tp:docstring>
|
||||
Send account registration (REGISTER) to the registrar.
|
||||
</tp:docstring>
|
||||
the account if expire=1, unregister if expire=0.
|
||||
Register the account if enable=true, unregister if enable=false.
|
||||
|
||||
@param[in] input accountID
|
||||
-->
|
||||
@ -199,10 +199,10 @@
|
||||
The account ID
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="i" name="expire" direction="in">
|
||||
<arg type="b" name="enable" direction="in">
|
||||
<tp:docstring>
|
||||
<p>To register, expire must be 1.</p>
|
||||
<p>To un-register, expire must be 0.</p>
|
||||
<p>To register, enable must be true.</p>
|
||||
<p>To un-register, enable must be false.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
@ -560,7 +560,7 @@ void Call::refuse()
|
||||
void Call::acceptTransf()
|
||||
{
|
||||
CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
|
||||
qDebug() << "Accepting call and transfering it to number : " << m_TransferNumber << ". callId : " << m_CallId;
|
||||
qDebug() << "Accepting call and transferring it to number : " << m_TransferNumber << ". callId : " << m_CallId;
|
||||
callManager.accept(m_CallId);
|
||||
callManager.transfer(m_CallId, m_TransferNumber);
|
||||
// m_HistoryState = TRANSFERED;
|
||||
@ -634,7 +634,7 @@ void Call::call()
|
||||
void Call::transfer()
|
||||
{
|
||||
CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance();
|
||||
qDebug() << "Transfering call to number : " << m_TransferNumber << ". callId : " << m_CallId;
|
||||
qDebug() << "Transferring call to number : " << m_TransferNumber << ". callId : " << m_CallId;
|
||||
callManager.transfer(m_CallId, m_TransferNumber);
|
||||
this->m_pStopTime = new QDateTime(QDateTime::currentDateTime());
|
||||
}
|
||||
|
Reference in New Issue
Block a user