mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
[#2519] Add internal SIP transport map and implement acwuireTransport method
acquireTransport create a transport and look if available in the map if unable to create it.
This commit is contained in:
@ -407,6 +407,29 @@ std::string SIPAccount::getLoginName (void)
|
||||
return username;
|
||||
}
|
||||
|
||||
std::string SIPAccount::getTransportMapKey(void)
|
||||
{
|
||||
std::string mapKey;
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
out << getLocalPort();
|
||||
std::string localAddress = getLocalAddress();
|
||||
std::string localPort = out.str();
|
||||
|
||||
out.seekp (0);
|
||||
out << getPublishedPort();
|
||||
std::string publishedAddress = getPublishedAddress();
|
||||
std::string publishedPort = out.str();
|
||||
|
||||
mapKey.append(localAddress.c_str());
|
||||
mapKey.append(localPort.c_str());
|
||||
mapKey.append(publishedAddress.c_str());
|
||||
mapKey.append(publishedPort.c_str());
|
||||
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
|
||||
std::string SIPAccount::getFromUri (void)
|
||||
{
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef SIPACCOUNT_H
|
||||
#define SIPACCOUNT_H
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "account.h"
|
||||
#include "sipvoiplink.h"
|
||||
#include "pjsip/sip_transport_tls.h"
|
||||
@ -268,7 +270,9 @@ class SIPAccount : public Account
|
||||
|
||||
inline void setAccountTransport (pjsip_transport *transport) { _transport = transport; }
|
||||
|
||||
private:
|
||||
std::string getTransportMapKey(void);
|
||||
|
||||
private:
|
||||
|
||||
/* Maps a string description of the SSL method
|
||||
* to the corresponding enum value in pjsip_ssl_method.
|
||||
@ -283,10 +287,10 @@ class SIPAccount : public Account
|
||||
*/
|
||||
void initTlsConfiguration(void);
|
||||
|
||||
/*
|
||||
* Initializes STUN config from the config file
|
||||
*/
|
||||
void initStunConfiguration (void);
|
||||
/*
|
||||
* Initializes STUN config from the config file
|
||||
*/
|
||||
void initStunConfiguration (void);
|
||||
|
||||
/*
|
||||
* Initializes set of additional credentials, if supplied by the user.
|
||||
@ -308,8 +312,7 @@ class SIPAccount : public Account
|
||||
* @return std::string The login name under which SFLPhone is running.
|
||||
*/
|
||||
std::string getLoginName(void);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// The pjsip client registration information
|
||||
pjsip_regc *_regc;
|
||||
@ -319,9 +322,9 @@ class SIPAccount : public Account
|
||||
// Network settings
|
||||
std::string _registrationExpire;
|
||||
|
||||
// Flag which determine if _localIpAddress or _publishedIpAddress is used in
|
||||
// Flag which determine if _localIpAddress or _publishedIpAddress is used in
|
||||
// sip headers
|
||||
bool _publishedSameasLocal;
|
||||
bool _publishedSameasLocal;
|
||||
|
||||
std::string _localIpAddress;
|
||||
std::string _publishedIpAddress;
|
||||
@ -350,8 +353,8 @@ class SIPAccount : public Account
|
||||
// The STUN server name, if applicable
|
||||
pj_str_t _stunServerName;
|
||||
|
||||
// The STUN server port, if applicable
|
||||
pj_uint16_t _stunPort;
|
||||
// The STUN server port, if applicable
|
||||
pj_uint16_t _stunPort;
|
||||
|
||||
// Display Name that can be used in SIP URI.
|
||||
std::string _displayName;
|
||||
|
@ -408,7 +408,6 @@ int SIPVoIPLink::sendRegister (AccountID id)
|
||||
_debug ("In sendRegister: account is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Resolve hostname here and keep its
|
||||
// IP address for the whole time the
|
||||
@ -451,40 +450,9 @@ int SIPVoIPLink::sendRegister (AccountID id)
|
||||
}
|
||||
}
|
||||
|
||||
// Launch a new TLS listener/transport
|
||||
// if the user did choose it.
|
||||
if (account->isTlsEnabled()) {
|
||||
pj_status_t status;
|
||||
|
||||
_debug (" sendRegister: createTlsTransport\n");
|
||||
status = createTlsTransportRetryOnFailure (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Failed to initialize TLS transport for account %s\n", id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// Launch a new UDP listener/transport, using the published address
|
||||
if (account->isStunEnabled ()) {
|
||||
pj_status_t status;
|
||||
|
||||
_debug (" sendRegister: createAlternateUdpTransport\n");
|
||||
status = createAlternateUdpTransport (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Failed to initialize UDP transport with an extern published address for account %s\n", id.c_str());
|
||||
}
|
||||
} else {
|
||||
|
||||
status = createUDPServer (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Use the local UDP transport\n");
|
||||
account->setAccountTransport (_localUDPTransport);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create SIP transport or get SIP transport from internal map
|
||||
acquireTransport(account->getAccountID());
|
||||
|
||||
_mutexSIP.enterMutex();
|
||||
|
||||
@ -1990,6 +1958,139 @@ pj_status_t SIPVoIPLink::stunServerResolve (AccountID id)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SIPVoIPLink::acquireTransport(const AccountID& accountID) {
|
||||
|
||||
SIPAccount* account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (accountID));
|
||||
|
||||
if(!account)
|
||||
return false;
|
||||
|
||||
// Try to create a new transport
|
||||
if(createSipTransport(accountID)) {
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
||||
_debug("Searching transport (%s) in transport map\n", account->getTransportMapKey().c_str());
|
||||
|
||||
// Could not create new transport, this transport may already exists
|
||||
SipTransportMap::iterator transport;
|
||||
transport = _transportMap.find(account->getTransportMapKey());
|
||||
|
||||
if(transport != _transportMap.end()) {
|
||||
|
||||
// Transport already exist, use it for this account
|
||||
_debug("Found transport (%s) in transport map\n", account->getTransportMapKey().c_str());
|
||||
|
||||
pjsip_transport* tr = transport->second;
|
||||
|
||||
account->setAccountTransport(tr);
|
||||
|
||||
|
||||
// Test is the associated transport is shutdowning
|
||||
if(account->getAccountTransport()) {
|
||||
|
||||
pjsip_transport* tp = account->getAccountTransport();
|
||||
|
||||
pj_lock_acquire(tp->lock);
|
||||
|
||||
// associated transport is shutdowning, resurect it!!!
|
||||
if(tp->is_shutdown == PJ_TRUE) {
|
||||
|
||||
_debug("Transport is shutdowning, cancel timer and reactivate it.\n");
|
||||
|
||||
pjsip_endpt_cancel_timer(_endpt, &(tp->idle_timer));
|
||||
tp->is_shutdown = PJ_FALSE;
|
||||
}
|
||||
|
||||
pj_lock_release(tp->lock);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
||||
// Transport could not either be created, socket not available
|
||||
_debug("Found transport (%s) in transport map\n", account->getTransportMapKey().c_str());
|
||||
|
||||
// Transport could not either be created, socket not available
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SIPVoIPLink::createSipTransport(AccountID id) {
|
||||
|
||||
|
||||
SIPAccount* account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
|
||||
|
||||
if (!account)
|
||||
return false;
|
||||
|
||||
pj_status_t status;
|
||||
|
||||
// Launch a new TLS listener/transport
|
||||
// if the user did choose it.
|
||||
if (account->isTlsEnabled()) {
|
||||
|
||||
_debug (" sendRegister: createTlsTransport\n");
|
||||
status = createTlsTransportRetryOnFailure (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Failed to initialize TLS transport for account %s\n", id.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Launch a new UDP listener/transport, using the published address
|
||||
if (account->isStunEnabled ()) {
|
||||
|
||||
_debug (" sendRegister: createAlternateUdpTransport\n");
|
||||
status = createAlternateUdpTransport (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Failed to initialize UDP transport with an extern published address for account %s\n", id.c_str());
|
||||
}
|
||||
} else {
|
||||
|
||||
status = createUDPServer (id);
|
||||
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Failed to initialize UDP transport for account %s\n", id.c_str());
|
||||
}
|
||||
|
||||
// We should not bind account to local udp transport here since we must
|
||||
/*
|
||||
if (status != PJ_SUCCESS) {
|
||||
_debug ("Use the local UDP transport\n");
|
||||
account->setAccountTransport (_localUDPTransport);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// If Transport created succesfully, store it in the internal map
|
||||
if(status == PJ_SUCCESS) {
|
||||
|
||||
std::string key = account->getTransportMapKey();
|
||||
pjsip_transport* transport = account->getAccountTransport();
|
||||
|
||||
_debug("Storing the newly created transport in transport map using key %s\n", key.c_str());
|
||||
_transportMap.insert(pair<std::string, pjsip_transport*>(key, transport));
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SIPVoIPLink::createUDPServer (AccountID id)
|
||||
{
|
||||
|
||||
@ -2176,6 +2277,8 @@ std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_
|
||||
return std::string (localAddress.ptr, localAddress.slen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pj_status_t SIPVoIPLink::init_transport_selector (pjsip_transport *transport, pjsip_tpselector **tp_sel)
|
||||
{
|
||||
pjsip_tpselector *tp;
|
||||
@ -2530,10 +2633,14 @@ void SIPVoIPLink::shutdownSipTransport(const AccountID& accountID)
|
||||
// PJSIP's UDP transport is considered permanent, reference counter
|
||||
// is incremented by 1 at transport creation.
|
||||
// To destroy this transport, reference counter must be zero
|
||||
|
||||
status = pjsip_transport_dec_ref(account->getAccountTransport());
|
||||
status = pjsip_transport_shutdown(account->getAccountTransport());
|
||||
|
||||
account->setAccountTransport(NULL);
|
||||
// account->getAccountTransport())->is_paused = PJ_TRUE;
|
||||
// pjsip_udp_transport_pause(account->getAccountTransport(), PJSIP_UDP_TRANSPORT_DESTROY_SOCKET);
|
||||
|
||||
// account->setAccountTransport(NULL);
|
||||
|
||||
}
|
||||
|
||||
@ -3104,7 +3211,7 @@ mod_on_rx_request (pjsip_rx_data *rdata)
|
||||
// Handle the incoming call invite in this function
|
||||
_debug ("UserAgent: Callback on_rx_request is involved! \n");
|
||||
|
||||
_debug("Receiving request using transport: %s %s (refcnt=%d)\n",
|
||||
_debug("Receiving REQUEST using transport: %s %s (refcnt=%d)\n",
|
||||
rdata->tp_info.transport->obj_name,
|
||||
rdata->tp_info.transport->info,
|
||||
(int)pj_atomic_get(rdata->tp_info.transport->ref_cnt));
|
||||
@ -3270,7 +3377,7 @@ mod_on_rx_request (pjsip_rx_data *rdata)
|
||||
link->init_transport_selector (account->getAccountTransport (), &tp);
|
||||
|
||||
if(account->getAccountTransport()) {
|
||||
_debug("Answer invite request using transport: %s %s (refcnt=%i)\n",
|
||||
_debug("Process INVITE request using transport: %s %s (refcnt=%i)\n",
|
||||
account->getAccountTransport()->obj_name,
|
||||
account->getAccountTransport()->info,
|
||||
(int)pj_atomic_get(account->getAccountTransport()->ref_cnt));
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include <pjnath/stun_config.h>
|
||||
///////////////////////////////
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
class EventThread;
|
||||
class SIPCall;
|
||||
|
||||
@ -45,6 +48,8 @@ class SIPCall;
|
||||
// To set the verbosity. From 0 (min) to 6 (max)
|
||||
#define PJ_LOG_LEVEL 6
|
||||
|
||||
#define SipTransportMap std::map<std::string, pjsip_transport*>
|
||||
|
||||
/**
|
||||
* @file sipvoiplink.h
|
||||
* @brief Specific VoIPLink for SIP (SIP core for incoming and outgoing events).
|
||||
@ -286,15 +291,22 @@ class SIPVoIPLink : public VoIPLink
|
||||
*/
|
||||
std::vector<std::string> getAllIpInterface(void);
|
||||
|
||||
/**
|
||||
* Initialize the transport selector
|
||||
* @param transport A transport associated with an account
|
||||
* @param tp_sel A pointer to receive the transport selector structure
|
||||
*
|
||||
* @return pj_status_t PJ_SUCCESS if the structure was successfully initialized
|
||||
*/
|
||||
pj_status_t init_transport_selector (pjsip_transport *transport, pjsip_tpselector **tp_sel);
|
||||
|
||||
/**
|
||||
* Initialize the transport selector
|
||||
* @param transport A transport associated with an account
|
||||
* @param tp_sel A pointer to receive the transport selector structure
|
||||
*
|
||||
* @return pj_status_t PJ_SUCCESS if the structure was successfully initialized
|
||||
*/
|
||||
pj_status_t init_transport_selector (pjsip_transport *transport, pjsip_tpselector **tp_sel);
|
||||
|
||||
/**
|
||||
* Requests PJSIP library for local IP address, using pj_gethostbyname()
|
||||
* @param addr* A string to be initialized
|
||||
*
|
||||
* @return bool True if addr successfully initialized
|
||||
*/
|
||||
bool loadSIPLocalIP (std::string *addr);
|
||||
|
||||
/**
|
||||
@ -346,6 +358,24 @@ class SIPVoIPLink : public VoIPLink
|
||||
|
||||
pj_status_t stunServerResolve (AccountID id);
|
||||
|
||||
|
||||
/**
|
||||
* Function used to create a new sip transport or get an existing one from the map.
|
||||
* The SIP transport is "acquired" according to account's current settings.
|
||||
* This function should be called before registering an account
|
||||
* @param accountID An account id for which transport is to be set
|
||||
*
|
||||
* @return bool True if the account is succesfully created or
|
||||
* successfully obtained from the transport map
|
||||
*/
|
||||
bool acquireTransport(const AccountID& accountID);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new sip transport according to the trasport type specified in account settings
|
||||
*/
|
||||
bool createSipTransport(AccountID id);
|
||||
|
||||
/** Create SIP UDP Listener */
|
||||
int createUDPServer (AccountID = "");
|
||||
|
||||
@ -378,7 +408,9 @@ class SIPVoIPLink : public VoIPLink
|
||||
pj_status_t createTlsTransport(AccountID id);
|
||||
|
||||
pj_status_t createAlternateUdpTransport (AccountID id);
|
||||
|
||||
|
||||
SipTransportMap _transportMap;
|
||||
|
||||
/** For registration use only */
|
||||
int _regPort;
|
||||
|
||||
|
Reference in New Issue
Block a user