Skip to content
Snippets Groups Projects
Commit 904f7882 authored by Alexandre Savard's avatar Alexandre Savard
Browse files

#9910: create new udp transport to fix registration failure with 606 error & received parameter

parent 2cbee41e
Branches
Tags
No related merge requests found
......@@ -511,7 +511,11 @@ class SIPAccount : public Account {
*/
static void keepAliveRegistrationCb(pj_timer_heap_t *th, pj_timer_entry *te);
/**
* Pointer to the transport used by this acccount
*/
pjsip_transport* transport_;
private:
NON_COPYABLE(SIPAccount);
......
......@@ -54,6 +54,7 @@
#include "sipaccount.h"
#include "pjsip/sip_types.h"
#include "dbus/dbusmanager.h"
#include "dbus/configurationmanager.h"
......@@ -428,6 +429,9 @@ SipTransport::createUdpTransport(const std::string &interface, unsigned int port
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr);
pj_status_t status;
pjsip_transport *transport = NULL;
if (boundAddr.addr.sa_family == pj_AF_INET()) {
status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, NULL, 1, &transport);
if (status != PJ_SUCCESS) {
......@@ -448,6 +452,53 @@ SipTransport::createUdpTransport(const std::string &interface, unsigned int port
return transport;
}
pjsip_transport *
SipTransport::createUdpTransport(const std::string &interface, unsigned int port, std::string& publicAddr, unsigned int publicPort)
{
// init socket to bind this transport to
pj_uint16_t listeningPort = (pj_uint16_t) port;
pjsip_transport *transport;
DEBUG("SipTransport: Update UDP transport on %s:%d with public addr %s:%d", interface.c_str(), port, publicAddr.c_str(), publicPort);
// determine the ip address for this transport
std::string listeningAddress;
if (interface == DEFAULT_INTERFACE)
listeningAddress = getSIPLocalIP();
else
listeningAddress = getInterfaceAddrFromName(interface);
if (listeningAddress.empty()) {
ERROR("SipTransport: Could not determine ip address for this transport");
return NULL;
}
std::ostringstream fullAddress;
fullAddress << listeningAddress << ":" << listeningPort;
pj_str_t udpString;
std::string fullAddressStr(fullAddress.str());
pj_cstr(&udpString, fullAddressStr.c_str());
pj_sockaddr boundAddr;
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &udpString, &boundAddr);
pj_str_t public_addr = pj_str((char *) publicAddr.c_str());
pjsip_host_port hostPort;
hostPort.host = public_addr;
hostPort.port = publicPort;
pj_status_t status;
// status = pjsip_udp_transport_restart(transport, PJSIP_UDP_TRANSPORT_DESTROY_SOCKET, PJ_INVALID_SOCKET, &boundAddr.ipv4, &hostPort);
status = pjsip_udp_transport_start(endpt_, &boundAddr.ipv4, &hostPort, 1, &transport);
if (status != PJ_SUCCESS) {
ERROR("SipTransport: Could not start new transport with address %s:%d, error code %d", publicAddr.c_str(), publicPort, status);
}
// dump debug information to stdout
pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_));
return transport;
}
pjsip_tpselector *SipTransport::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const
{
if (!transport) {
......
......@@ -101,6 +101,10 @@ class SipTransport {
*/
void createSipTransport(SIPAccount &account);
/**
* Create the default sip transport on 5060. In case this port is already used
* increme
*/
void createDefaultSipUdpTransport();
/**
......@@ -126,6 +130,18 @@ class SipTransport {
*/
void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const;
/**
* Create a new udp transport specifying the bound address AND the published address.
* The published address is the address to appears in the sip VIA header. This is used
* essentially when the client is behind a trafic routing device.
*
* @param The interface to bind this transport with
* @param The requested udp port number
* @param The public address for this transport
* @param The public port for this transport
*/
pjsip_transport *createUdpTransport(const std::string &interface, unsigned int port, std::string& publicAddr, unsigned int publicPort);
private:
NON_COPYABLE(SipTransport);
......
......@@ -489,6 +489,7 @@ bool SIPVoIPLink::getEvent()
void SIPVoIPLink::sendRegister(Account *a)
{
SIPAccount *account = dynamic_cast<SIPAccount*>(a);
if (!account)
throw VoipLinkException("SipVoipLink: Account is not SIPAccount");
sipTransport.createSipTransport(*account);
......@@ -511,12 +512,19 @@ void SIPVoIPLink::sendRegister(Account *a)
std::string from(account->getFromUri());
pj_str_t pjFrom = pj_str((char*) from.c_str());
// Get the contact header for this account
std::string contact(account->getContactHeader());
// Get the received header
std::string received(account->getReceivedParameter());
// Get the contact header
std::string contact = account->getContactHeader();
pj_str_t pjContact = pj_str((char*) contact.c_str());
std::string received(account->getReceivedParameter());
pj_str_t pjReceived = pj_str((char *) received.c_str());
if(!received.empty()) {
// Set received parameter string to empty in order to avoid creating new transport for each register
account->setReceivedParameter("");
// Explicitely set the bound address port to 0 so that pjsip determine a random port by itself
account->transport_= sipTransport.createUdpTransport(account->getLocalInterface(), 0, received, account->getLocalPort());
}
if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account->getRegistrationExpire()) != PJ_SUCCESS)
throw VoipLinkException("Unable to initialize account registration structure");
......@@ -536,7 +544,6 @@ void SIPVoIPLink::sendRegister(Account *a)
pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
pjsip_regc_add_headers(regc, &hdr_list);
pjsip_tx_data *tdata;
if (pjsip_regc_register(regc, PJ_TRUE, &tdata) != PJ_SUCCESS)
......@@ -1588,6 +1595,11 @@ void registration_cb(pjsip_regc_cbparam *param)
return;
}
if(param->code == 200) {
account->setRegister(true);
account->setRegistrationState(Registered);
}
if (account->isContactUpdateEnabled())
update_contact_header(param, account);
......@@ -1615,6 +1627,7 @@ void registration_cb(pjsip_regc_cbparam *param)
case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE:
lookForReceivedParameter(param, account);
account->setRegistrationState(ErrorNotAcceptable);
SIPVoIPLink::instance()->sendRegister(account);
break;
case PJSIP_SC_SERVICE_UNAVAILABLE:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment