Commit ce0baf39 authored by Adrien Béraud's avatar Adrien Béraud

sip: move account transport to SIPAccount

Refs #68179

Change-Id: I2f79ead5c23097b529fea9f0084734f4e85d0abf
parent 473115d5
......@@ -104,7 +104,6 @@ RingAccount::RingAccount(const std::string& accountID, bool /* presenceEnabled *
RingAccount::~RingAccount()
{
Manager::instance().unregisterEventHandler((uintptr_t)this);
setTransport();
dht_.join();
gnutls_global_deinit();
}
......@@ -1098,18 +1097,17 @@ std::string RingAccount::getToUri(const std::string& to) const
pj_str_t
RingAccount::getContactHeader(pjsip_transport* t)
{
if (!t && transport_)
t = transport_->get();
if (!t) {
RING_ERR("Transport not created yet");
pj_cstr(&contact_, "<sips:>");
RING_ERR("getContactHeader: no SIP transport provided");
contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE,
"<sips:%s@ring.dht>",
username_.c_str());
return contact_;
}
// FIXME: be sure that given transport is from SipIceTransport
auto tlsTr = reinterpret_cast<tls::SipsIceTransport::TransportData*>(t)->self;
auto address = tlsTr->getLocalAddress();
RING_WARN("getContactHeader %s@%s", username_.c_str(), address.toString(true).c_str());
contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE,
"<sips:%s%s%s;transport=%s>",
username_.c_str(),
......
......@@ -273,6 +273,64 @@ SIPAccount::newOutgoingCall(const std::string& toUrl)
return call;
}
void
SIPAccount::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info)
{
pj_status_t currentStatus = transportStatus_;
RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str());
if (!SipTransport::isAlive(transport_, state)) {
if (info) {
char err_msg[128];
err_msg[0] = '\0';
pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg));
transportStatus_ = info->status;
transportError_ = std::string(descr.ptr, descr.slen);
RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr);
}
else {
// This is already the generic error used by pjsip.
transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
transportError_ = "";
}
setRegistrationState(RegistrationState::ERROR_GENERIC);
setTransport();
}
else {
// The status can be '0', this is the same as OK
transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
transportError_ = "";
}
// Notify the client of the new transport state
if (currentStatus != transportStatus_)
emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails());
}
void
SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t)
{
if (t == transport_)
return;
if (transport_) {
RING_DBG("Removing transport from account");
if (regc_)
pjsip_regc_release_transport(regc_);
transport_->removeStateListener(reinterpret_cast<uintptr_t>(this));
}
transport_ = t;
if (transport_)
transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccount::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2));
}
pjsip_tpselector
SIPAccount::getTransportSelector() {
if (!transport_)
return SIPVoIPLink::getTransportSelector(nullptr);
return SIPVoIPLink::getTransportSelector(transport_->get());
}
std::shared_ptr<Call>
SIPAccount::newOutgoingCall(const std::string& toUrl)
{
......@@ -1589,16 +1647,6 @@ computeMd5HashFromCredential(const std::string& username,
return std::string(hash, 32);
}
void
SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t)
{
if (transport_ == t)
return;
if (transport_ && regc_)
pjsip_regc_release_transport(regc_);
SIPAccountBase::setTransport(t);
}
void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::string> >& creds)
{
// we can not authenticate without credentials
......
......@@ -437,7 +437,20 @@ class SIPAccount : public SIPAccountBase {
return keepAliveEnabled_;
}
virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
virtual inline std::shared_ptr<SipTransport> getTransport() {
return transport_;
}
inline pjsip_transport_type_e getTransportType() const {
return transportType_;
}
/**
* Shortcut for SipTransport::getTransportSelector(account.getTransport()).
*/
pjsip_tpselector getTransportSelector();
/* Returns true if the username and/or hostname match this account */
MatchRank matches(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
......@@ -519,6 +532,12 @@ class SIPAccount : public SIPAccountBase {
bool hostnameMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
bool proxyMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
/**
* Callback called by the transport layer when the registration
* transport state changes.
*/
virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info);
struct {
pj_bool_t active; /**< Flag of reregister status. */
pj_timer_entry timer; /**< Timer for reregistration. */
......
......@@ -53,9 +53,7 @@ SIPAccountBase::SIPAccountBase(const std::string& accountID)
: Account(accountID), link_(getSIPVoIPLink())
{}
SIPAccountBase::~SIPAccountBase() {
setTransport();
}
SIPAccountBase::~SIPAccountBase() {}
template <typename T>
static void
......@@ -253,55 +251,6 @@ SIPAccountBase::getVolatileAccountDetails() const
return a;
}
void
SIPAccountBase::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info)
{
pj_status_t currentStatus = transportStatus_;
RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str());
if (!SipTransport::isAlive(transport_, state)) {
if (info) {
char err_msg[128];
err_msg[0] = '\0';
pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg));
transportStatus_ = info->status;
transportError_ = std::string(descr.ptr, descr.slen);
RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr);
}
else {
// This is already the generic error used by pjsip.
transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
transportError_ = "";
}
setRegistrationState(RegistrationState::ERROR_GENERIC);
setTransport();
}
else {
// The status can be '0', this is the same as OK
transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
transportError_ = "";
}
// Notify the client of the new transport state
if (currentStatus != transportStatus_)
emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails());
}
void
SIPAccountBase::setTransport(const std::shared_ptr<SipTransport>& t)
{
if (t == transport_)
return;
if (transport_) {
RING_DBG("Removing transport from account");
transport_->removeStateListener(reinterpret_cast<uintptr_t>(this));
}
transport_ = t;
if (transport_)
transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccountBase::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2));
}
auto
SIPAccountBase::getPortsReservation() noexcept -> decltype(getPortsReservation())
{
......@@ -345,11 +294,4 @@ SIPAccountBase::generateVideoPort() const
}
#endif
pjsip_tpselector
SIPAccountBase::getTransportSelector() {
if (!transport_)
return SIPVoIPLink::getTransportSelector(nullptr);
return SIPVoIPLink::getTransportSelector(transport_->get());
}
} // namespace ring
......@@ -248,23 +248,10 @@ public:
virtual std::string getToUri(const std::string& username) const = 0;
virtual std::string getServerUri() const = 0;
virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
inline const std::shared_ptr<SipTransport>& getTransport() {
return transport_;
}
inline pjsip_transport_type_e getTransportType() const {
return transportType_;
virtual inline std::shared_ptr<SipTransport> getTransport() {
return nullptr;
}
/**
* Shortcut for SipTransport::getTransportSelector(account.getTransport()).
*/
pjsip_tpselector getTransportSelector();
/**
* Socket port generators for media
* Note: given ports are application wide, a port cannot be given again
......@@ -292,12 +279,6 @@ protected:
*/
virtual std::map<std::string, std::string> getVolatileAccountDetails() const;
/**
* Callback called by the transport layer when the registration
* transport state changes.
*/
virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info);
/**
* Voice over IP Link contains a listener thread and calls
*/
......
......@@ -889,10 +889,18 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this());
const auto& account = call->getSIPAccount();
auto family = pj_AF_INET();
// FIXME : for now, use the same address family as the SIP transport
auto family = pjsip_transport_type_get_af(account.getTransportType());
IpAddr addrToUse = ip_utils::getInterfaceAddr(account.getLocalInterface(), family);
if (auto dlg = inv->dlg) {
if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
if (auto tr = dlg->tp_sel.u.transport)
family = tr->local_addr.addr.sa_family;
} else if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
if (auto tr = dlg->tp_sel.u.listener)
family = tr->local_addr.addr.sa_family;
}
}
auto ifaceAddr = ip_utils::getInterfaceAddr(account.getLocalInterface(), family);
IpAddr address;
if (account.getUPnPActive()) {
......@@ -901,11 +909,11 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
account.getUPnPIpAddress() : account.getPublishedIpAddress();
} else {
address = account.getPublishedSameasLocal() ?
addrToUse : account.getPublishedIpAddress();
ifaceAddr : account.getPublishedIpAddress();
}
/* fallback on local address */
if (not address) address = addrToUse;
if (not address) address = ifaceAddr;
call->setCallMediaLocal(address);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment