[#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:
Alexandre Savard
2009-12-14 11:10:17 -05:00
parent 5fa082c773
commit 395e37df4e
4 changed files with 222 additions and 57 deletions

View File

@ -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)
{

View File

@ -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;

View File

@ -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));

View File

@ -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;