mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
#3674: refactor contact header generation, add update contact header in registration_cb
This commit is contained in:
@ -56,6 +56,7 @@ SIPAccount::SIPAccount(const std::string& accountID)
|
||||
, transportType_(PJSIP_TRANSPORT_UNSPECIFIED)
|
||||
, cred_(NULL)
|
||||
, tlsSetting_()
|
||||
, contactHeader_()
|
||||
, stunServerName_()
|
||||
, stunPort_(0)
|
||||
, dtmfType_(OVERRTP)
|
||||
@ -755,11 +756,20 @@ std::string SIPAccount::getServerUri() const
|
||||
return "<" + scheme + hostname_ + transport + ">";
|
||||
}
|
||||
|
||||
std::string SIPAccount::getContactHeader(const std::string& address, const std::string& port) const
|
||||
std::string SIPAccount::getContactHeader() const
|
||||
{
|
||||
std::string scheme;
|
||||
std::string transport;
|
||||
|
||||
// Use the CONTACT header provided by the registrar if any
|
||||
if(!contactHeader_.empty())
|
||||
return contactHeader_;
|
||||
|
||||
// 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);
|
||||
|
||||
// UDP does not require the transport specification
|
||||
if (transportType_ == PJSIP_TRANSPORT_TLS) {
|
||||
scheme = "sips:";
|
||||
|
@ -117,15 +117,45 @@ class SIPAccount : public Account {
|
||||
registrationStateDetailed_ = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize internal state of this account for configuration
|
||||
* @param YamlEmitter the configuration engine which generate the configuration file
|
||||
*/
|
||||
virtual void serialize(Conf::YamlEmitter *emitter);
|
||||
|
||||
/**
|
||||
* Populate the internal state for this account based on info stored in the configuration file
|
||||
* @param The configuration node for this account
|
||||
*/
|
||||
virtual void unserialize(Conf::MappingNode *map);
|
||||
|
||||
/**
|
||||
* Set the internal state for this account, mainly used to manage account details from the client application.
|
||||
* @param The map containing the account information.
|
||||
*/
|
||||
virtual void setAccountDetails(std::map<std::string, std::string> details);
|
||||
|
||||
/**
|
||||
* Return an map containing the internal state of this account. Client application can use this method to manage
|
||||
* account info.
|
||||
* @return A map containing the account information.
|
||||
*/
|
||||
virtual std::map<std::string, std::string> getAccountDetails() const;
|
||||
|
||||
/**
|
||||
* Return the information for the default IP to IP account
|
||||
*/
|
||||
std::map<std::string, std::string> getIp2IpDetails() const;
|
||||
|
||||
/**
|
||||
* Return the TLS settings, mainly used to return security information to
|
||||
* a client application
|
||||
*/
|
||||
std::map<std::string, std::string> getTlsSettings() const;
|
||||
|
||||
/**
|
||||
* Manage the TLS settings from a client application
|
||||
*/
|
||||
void setTlsSettings(const std::map<std::string, std::string>& details);
|
||||
|
||||
/**
|
||||
@ -189,7 +219,7 @@ class SIPAccount : public Account {
|
||||
|
||||
/**
|
||||
* Set the expiration for this account as found in
|
||||
* the "Expire" sip header or the Contact "expire" param.
|
||||
* the "Expire" sip header or the CONTACT's "expire" param.
|
||||
*/
|
||||
void setRegistrationExpire(int expire) {
|
||||
if(expire > 0)
|
||||
@ -197,7 +227,7 @@ class SIPAccount : public Account {
|
||||
}
|
||||
|
||||
/**
|
||||
* Doubles the Expiration Interval of Contact Addresses.
|
||||
* Doubles the Expiration Interval sepecified for registration.
|
||||
*/
|
||||
void doubleRegistrationExpire() {
|
||||
registrationExpire_ *= 2;
|
||||
@ -228,7 +258,6 @@ class SIPAccount : public Account {
|
||||
* Get the registration stucture that is used
|
||||
* for PJSIP in the registration process.
|
||||
* Settings are loaded from configuration file.
|
||||
* @param void
|
||||
* @return pjsip_regc* A pointer to the registration structure
|
||||
*/
|
||||
pjsip_regc* getRegistrationInfo() {
|
||||
@ -330,11 +359,20 @@ class SIPAccount : public Account {
|
||||
std::string getServerUri() const;
|
||||
|
||||
/**
|
||||
* Set the contact header
|
||||
* @param port Optional port. Otherwise set to the port defined for that account.
|
||||
* @param hostname Optional local address. Otherwise set to the hostname defined for that account.
|
||||
*/
|
||||
void setContactHeader(std::string& contact)
|
||||
{
|
||||
contactHeader_ = contact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact header for
|
||||
* @return pj_str_t The contact header based on account information
|
||||
*/
|
||||
std::string getContactHeader(const std::string& address, const std::string& port) const;
|
||||
std::string getContactHeader(void) const;
|
||||
|
||||
/**
|
||||
* Get the local interface name on which this account is bound.
|
||||
@ -508,25 +546,60 @@ class SIPAccount : public Account {
|
||||
*/
|
||||
pj_uint16_t tlsListenerPort_;
|
||||
|
||||
/**
|
||||
* Transport type used for this sip account. Currently supported types:
|
||||
* PJSIP_TRANSPORT_UNSPECIFIED
|
||||
* PJSIP_TRANSPORT_UDP
|
||||
* PJSIP_TRANSPORT_TLS
|
||||
*/
|
||||
pjsip_transport_type_e transportType_;
|
||||
|
||||
//Credential information
|
||||
/**
|
||||
* Credential information stored for further registration.
|
||||
*/
|
||||
pjsip_cred_info *cred_;
|
||||
|
||||
// The TLS settings, if tls is chosen as
|
||||
// a sip transport.
|
||||
/**
|
||||
* The TLS settings, used only if tls is chosen as a sip transport.
|
||||
*/
|
||||
pjsip_tls_setting tlsSetting_;
|
||||
|
||||
// The STUN server name, if applicable for internal use only
|
||||
/**
|
||||
* The CONTACT header used for registration as provided by the registrar, this value could differ
|
||||
* from the host name in case the registrar is inside a subnetwork (such as a VPN).
|
||||
* The header will be stored
|
||||
*/
|
||||
std::string contactHeader_;
|
||||
|
||||
/**
|
||||
* The STUN server name (hostname)
|
||||
*/
|
||||
pj_str_t stunServerName_;
|
||||
|
||||
// The STUN server port, if applicable
|
||||
/**
|
||||
* The STUN server port
|
||||
*/
|
||||
pj_uint16_t stunPort_;
|
||||
|
||||
/**
|
||||
* DTMF type used for this account SIPINFO or RTP
|
||||
*/
|
||||
DtmfType dtmfType_;
|
||||
|
||||
/**
|
||||
* Determine if TLS is enabled for this account. TLS provides a secured channel for
|
||||
* SIP signalization. It is independant than the media encription provided by SRTP or ZRTP.
|
||||
*/
|
||||
std::string tlsEnable_;
|
||||
|
||||
/**
|
||||
* Specify the TLS port
|
||||
*/
|
||||
int tlsPort_;
|
||||
|
||||
/**
|
||||
* Certificate autority file
|
||||
*/
|
||||
std::string tlsCaListFile_;
|
||||
std::string tlsCertificateFile_;
|
||||
std::string tlsPrivateKeyFile_;
|
||||
@ -540,21 +613,56 @@ class SIPAccount : public Account {
|
||||
std::string tlsNegotiationTimeoutSec_;
|
||||
std::string tlsNegotiationTimeoutMsec_;
|
||||
|
||||
/**
|
||||
* The stun server hostname (optional), used to provide the public IP address in case the softphone
|
||||
* stay behind a NAT.
|
||||
*/
|
||||
std::string stunServer_;
|
||||
|
||||
/**
|
||||
* Determine if STUN public address resolution is required to register this account. In this case a
|
||||
* STUN server hostname must be specified.
|
||||
*/
|
||||
bool stunEnabled_;
|
||||
|
||||
/**
|
||||
* Determine if SRTP is enabled for this account, SRTP and ZRTP are mutually exclusive
|
||||
* This only determine if the media channel is secured. One could only enable TLS
|
||||
* with no secured media channel.
|
||||
*/
|
||||
bool srtpEnabled_;
|
||||
|
||||
/**
|
||||
* Specifies the type of key exchange usd for SRTP (sdes/zrtp)
|
||||
*/
|
||||
std::string srtpKeyExchange_;
|
||||
|
||||
/**
|
||||
* Determine if the softphone should fallback on non secured media channel if SRTP negotiation fails.
|
||||
* Make sure other SIP endpoints share the same behavior since it could result in encrypted data to be
|
||||
* played through the audio device.
|
||||
*/
|
||||
bool srtpFallback_;
|
||||
|
||||
/**
|
||||
* Determine if the SAS sould be displayed on client side. SAS is a 4-charcter string
|
||||
* that end users should verbaly validate to ensure the channel is secured. Used especially
|
||||
* to prevent man-in-the-middle attack.
|
||||
*/
|
||||
bool zrtpDisplaySas_;
|
||||
|
||||
/**
|
||||
* Only display SAS 4-character string once at the begining of the call.
|
||||
*/
|
||||
bool zrtpDisplaySasOnce_;
|
||||
|
||||
bool zrtpHelloHash_;
|
||||
bool zrtpNotSuppWarning_;
|
||||
/*
|
||||
* Details about the registration state.
|
||||
* This is a protocol Code:Description pair.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Details about the registration state.
|
||||
* This is a protocol Code:Description pair.
|
||||
*/
|
||||
std::pair<int, std::string> registrationStateDetailed_;
|
||||
|
||||
/**
|
||||
@ -563,10 +671,6 @@ class SIPAccount : public Account {
|
||||
*/
|
||||
pj_timer_entry keepAliveTimer_;
|
||||
|
||||
/**
|
||||
* Delay coresponding to a registration interval
|
||||
*/
|
||||
// pj_time_val keepAliveDelay_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -296,14 +296,18 @@ void SIPVoIPLink::sendRegister(Account *a)
|
||||
|
||||
std::string srvUri(account->getServerUri());
|
||||
|
||||
std::string address, port;
|
||||
findLocalAddressFromUri(srvUri, account->transport_, address, port);
|
||||
// std::string address, port;
|
||||
// findLocalAddressFromUri(srvUri, account->transport_, address, port);
|
||||
pj_str_t pjSrv = pj_str((char*) srvUri.c_str());
|
||||
|
||||
// Generate the FROM header
|
||||
std::string from(account->getFromUri());
|
||||
pj_str_t pjFrom = pj_str((char*) from.c_str());
|
||||
std::string contact(account->getContactHeader(address, port));
|
||||
|
||||
// Store the CONTACT header for future usage
|
||||
// account->setContactHeader(address, port);
|
||||
std::string contact(account->getContactHeader());
|
||||
pj_str_t pjContact = pj_str((char*) contact.c_str());
|
||||
pj_str_t pjSrv = pj_str((char*) srvUri.c_str());
|
||||
|
||||
if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account->getRegistrationExpire()) != PJ_SUCCESS)
|
||||
throw VoipLinkException("Unable to initialize account registration structure");
|
||||
@ -803,16 +807,20 @@ SIPVoIPLink::SIPStartCall(SIPCall *call)
|
||||
|
||||
std::string toUri(call->getPeerNumber()); // expecting a fully well formed sip uri
|
||||
|
||||
std::string address, port;
|
||||
findLocalAddressFromUri(toUri, account->transport_, address, port);
|
||||
// std::string address, port;
|
||||
// findLocalAddressFromUri(toUri, account->transport_, address, port);
|
||||
|
||||
std::string from(account->getFromUri());
|
||||
pj_str_t pjFrom = pj_str((char*) from.c_str());
|
||||
std::string contact(account->getContactHeader(address, port));
|
||||
pj_str_t pjContact = pj_str((char*) contact.c_str());
|
||||
pj_str_t pjTo = pj_str((char*) toUri.c_str());
|
||||
|
||||
pjsip_dialog *dialog;
|
||||
// Create the from header
|
||||
std::string from(account->getFromUri());
|
||||
pj_str_t pjFrom = pj_str((char*) from.c_str());
|
||||
|
||||
// Get the contact header
|
||||
std::string contact(account->getContactHeader());
|
||||
pj_str_t pjContact = pj_str((char*) contact.c_str());
|
||||
|
||||
pjsip_dialog *dialog = NULL;
|
||||
|
||||
if (pjsip_dlg_create_uac(pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog) != PJ_SUCCESS)
|
||||
return false;
|
||||
@ -1130,7 +1138,7 @@ void SIPVoIPLink::createUdpTransport(SIPAccount *account)
|
||||
transportMap_[account->getLocalPort()] = account->transport_;
|
||||
}
|
||||
|
||||
pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool)
|
||||
pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const
|
||||
{
|
||||
assert(transport);
|
||||
pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector));
|
||||
@ -1199,67 +1207,62 @@ void SIPVoIPLink::shutdownSipTransport(SIPAccount *account)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SIPVoIPLink::findLocalAddressFromUri(const std::string& uri, pjsip_transport *transport, std::string& addr, std::string &port)
|
||||
void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const
|
||||
{
|
||||
// Initialize the sip port with the default SIP port
|
||||
std::stringstream ss;
|
||||
ss << DEFAULT_SIP_PORT;
|
||||
port = ss.str();
|
||||
|
||||
pjsip_uri *genericUri = pjsip_parse_uri(pool_, (char*)uri.data(), uri.size(), 0);
|
||||
|
||||
// Initialize the sip address with the hostname
|
||||
const pj_str_t *pjMachineName = pj_gethostname();
|
||||
addr = std::string(pjMachineName->ptr, pjMachineName->slen);
|
||||
|
||||
if (genericUri == NULL)
|
||||
// Update address and port with active transport
|
||||
if(!transport) {
|
||||
ERROR("SIPVoIPLink: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str());
|
||||
return;
|
||||
|
||||
pjsip_sip_uri *sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(genericUri);
|
||||
|
||||
if (sip_uri == NULL)
|
||||
return;
|
||||
|
||||
pjsip_transport_type_e transportType;
|
||||
|
||||
if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
|
||||
transportType = PJSIP_TRANSPORT_TLS;
|
||||
ss.str("");
|
||||
ss << DEFAULT_SIP_TLS_PORT;
|
||||
port = ss.str();
|
||||
} else {
|
||||
if (transport == NULL)
|
||||
transport = localUDPTransport_;
|
||||
|
||||
transportType = PJSIP_TRANSPORT_UDP;
|
||||
}
|
||||
|
||||
// get the transport manager associated with the SIP enpoint
|
||||
pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_);
|
||||
|
||||
if (!tpmgr)
|
||||
if (!tpmgr) {
|
||||
ERROR("SIPVoIPLink: Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
pjsip_tpselector *tp_sel = NULL;
|
||||
|
||||
if (transportType == PJSIP_TRANSPORT_UDP and transport)
|
||||
tp_sel = initTransportSelector(transport, pool_);
|
||||
// initialize a transport selector
|
||||
// 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) {
|
||||
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;
|
||||
|
||||
if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS)
|
||||
// Find the local address and port for this transport
|
||||
if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) {
|
||||
WARN("SIPVoIPLink: Could not retreive local address and port from transport, using %s:%s", addr.c_str(), port.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Update local address based on the transport type
|
||||
addr = std::string(localAddress.ptr, localAddress.slen);
|
||||
|
||||
|
||||
// Fallback on local ip provided by pj_gethostip()
|
||||
if (addr == "0.0.0.0")
|
||||
addr = getSIPLocalIP();
|
||||
|
||||
// Determine the local port based on transport information
|
||||
ss.str("");
|
||||
ss << i_port;
|
||||
port = ss.str();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
std::string parseDisplayName(const char * buffer)
|
||||
{
|
||||
@ -1605,13 +1608,77 @@ void transaction_state_changed_cb(pjsip_inv_session *inv UNUSED, pjsip_transacti
|
||||
}
|
||||
}
|
||||
|
||||
static 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;
|
||||
std::string currentContactHeader = "";
|
||||
|
||||
// if(!account->updateContactAllowed())
|
||||
// return;
|
||||
|
||||
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) {
|
||||
WARN("SIPVoIPLink: No contact header in registration callback");
|
||||
pj_pool_release(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
contact_hdr = param->contact[0];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string recvContactHost(uri->host.ptr, uri->host.slen);
|
||||
std::stringstream ss;
|
||||
ss << uri->port;
|
||||
std::string recvContactPort = ss.str();
|
||||
|
||||
DEBUG("SIPVoIPLink: Current contact header %s:%s", recvContactHost.c_str(), recvContactPort.c_str());
|
||||
|
||||
currentContactHeader = account->getContactHeader();
|
||||
DEBUG("SIPVoIPLink: Current contact header %s", currentContactHeader.c_str());
|
||||
// DEBUG("Received contact header %s",
|
||||
|
||||
pj_pool_release(pool);
|
||||
}
|
||||
|
||||
void registration_cb(struct pjsip_regc_cbparam *param)
|
||||
{
|
||||
SIPAccount *account = static_cast<SIPAccount *>(param->token);
|
||||
|
||||
if (account == NULL)
|
||||
return;
|
||||
ERROR("SipVoipLink: REGISTRATION CALLBACK");
|
||||
|
||||
if (account == NULL) {
|
||||
ERROR("SipVoipLink: account does'nt exist in registration callback");
|
||||
return;
|
||||
}
|
||||
|
||||
if (param == NULL) {
|
||||
ERROR("SipVoipLink: regsitration callback param is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("SipVoipLink: Contact header from UAS, %d contact(s)", param->contact_cnt);
|
||||
update_contact_header(param, account);
|
||||
|
||||
const pj_str_t *description = pjsip_get_status_text(param->code);
|
||||
|
||||
if (param->code && description) {
|
||||
|
@ -260,7 +260,7 @@ class SIPVoIPLink : public VoIPLink {
|
||||
*
|
||||
* @return A pointer to the transport selector structure
|
||||
*/
|
||||
pjsip_tpselector *initTransportSelector(pjsip_transport *, pj_pool_t *);
|
||||
pjsip_tpselector *initTransportSelector(pjsip_transport *, pj_pool_t *) const;
|
||||
|
||||
/**
|
||||
* This function unset the transport for a given account.
|
||||
@ -282,6 +282,16 @@ class SIPVoIPLink : public VoIPLink {
|
||||
*/
|
||||
void createDefaultSipUdpTransport();
|
||||
|
||||
/**
|
||||
* Get the correct address to use (ie advertised) from
|
||||
* a uri. The corresponding transport that should be used
|
||||
* with that uri will be discovered.
|
||||
*
|
||||
* @param uri The uri from which we want to discover the address to use
|
||||
* @param transport The transport to use to discover the address
|
||||
*/
|
||||
void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Start a SIP Call
|
||||
@ -331,16 +341,6 @@ class SIPVoIPLink : public VoIPLink {
|
||||
*/
|
||||
void createStunTransport(SIPAccount *account);
|
||||
|
||||
/**
|
||||
* Get the correct address to use (ie advertised) from
|
||||
* a uri. The corresponding transport that should be used
|
||||
* with that uri will be discovered.
|
||||
*
|
||||
* @param uri The uri from which we want to discover the address to use
|
||||
* @param transport The transport to use to discover the address
|
||||
*/
|
||||
void findLocalAddressFromUri(const std::string& uri, pjsip_transport *transport, std::string &address, std::string &port);
|
||||
|
||||
/**
|
||||
* UDP Transports are stored in this map in order to retreive them in case
|
||||
* several accounts would share the same port number.
|
||||
|
Reference in New Issue
Block a user