diff --git a/daemon/src/iax/iaxaccount.cpp b/daemon/src/iax/iaxaccount.cpp index 8bb3578edb0eab86b99db6e46464e42e24fe304c..f88c889f7d553adff84d4cb77d95de058eed64ad 100644 --- a/daemon/src/iax/iaxaccount.cpp +++ b/daemon/src/iax/iaxaccount.cpp @@ -140,7 +140,7 @@ void IAXAccount::registerVoIPLink() { try { link_.init(); - link_.sendRegister(this); + link_.sendRegister(*this); } catch (const VoipLinkException &e) { ERROR("IAXAccount: %s", e.what()); } @@ -150,7 +150,7 @@ void IAXAccount::unregisterVoIPLink() { try { - link_.sendUnregister(this); + link_.sendUnregister(*this); link_.terminate(); } catch (const VoipLinkException &e) { ERROR("IAXAccount: %s", e.what()); diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 990de886a21e890b6f3249ce1cf32d5a234b44d5..0b3dad5d11b263225841ba64a082455731decf41 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -155,8 +155,11 @@ IAXVoIPLink::getEvent() } } - if (nextRefreshStamp_ and nextRefreshStamp_ < time(NULL)) - sendRegister(Manager::instance().getIaxAccount(accountID_)); + if (nextRefreshStamp_ and nextRefreshStamp_ < time(NULL)) { + auto account = Manager::instance().getIaxAccount(accountID_); + if (account) + sendRegister(*account); + } sendAudioFromMic(); @@ -175,6 +178,17 @@ IAXVoIPLink::getCallIDs() return v; } +std::vector<Call*> +IAXVoIPLink::getCalls(const std::string &account_id) const +{ + std::vector<Call*> calls; + for (const auto & item : iaxCallMap_) { + if (item.second->getAccountId() == account_id) + calls.push_back(item.second); + } + return calls; +} + void IAXVoIPLink::sendAudioFromMic() { @@ -239,21 +253,18 @@ IAXVoIPLink::getIAXCall(const std::string& id) } void -IAXVoIPLink::sendRegister(Account *a) +IAXVoIPLink::sendRegister(Account& a) { - IAXAccount *account = static_cast<IAXAccount*>(a); - - if (!account) - throw VoipLinkException("Account is NULL"); - else if (not account->isEnabled()) { + IAXAccount& account = static_cast<IAXAccount&>(a); + if (not account.isEnabled()) { WARN("Account must be enabled to register, ignoring"); return; } - if (account->getHostname().empty()) + if (account.getHostname().empty()) throw VoipLinkException("Account hostname is empty"); - if (account->getUsername().empty()) + if (account.getUsername().empty()) throw VoipLinkException("Account username is empty"); std::lock_guard<std::mutex> lock(mutexIAX_); @@ -264,14 +275,14 @@ IAXVoIPLink::sendRegister(Account *a) regSession_ = iax_session_new(); if (regSession_) { - iax_register(regSession_, account->getHostname().data(), account->getUsername().data(), account->getPassword().data(), 120); + iax_register(regSession_, account.getHostname().data(), account.getUsername().data(), account.getPassword().data(), 120); nextRefreshStamp_ = time(NULL) + 10; - account->setRegistrationState(RegistrationState::TRYING); + account.setRegistrationState(RegistrationState::TRYING); } } void -IAXVoIPLink::sendUnregister(Account *a) +IAXVoIPLink::sendUnregister(Account& a) { if (regSession_) { std::lock_guard<std::mutex> lock(mutexIAX_); @@ -281,7 +292,7 @@ IAXVoIPLink::sendUnregister(Account *a) nextRefreshStamp_ = 0; - static_cast<IAXAccount*>(a)->setRegistrationState(RegistrationState::UNREGISTERED); + static_cast<IAXAccount&>(a).setRegistrationState(RegistrationState::UNREGISTERED); } Call* @@ -514,7 +525,7 @@ IAXVoIPLink::getIaxCall(const std::string& id) if (iter != iaxCallMap_.end()) return iter->second; else - return NULL; + return nullptr; } void diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index 4c385ff58c592ff8f98d631edc7fd04c6675629b..d0ecd06bcba29c4d8287e8051248121d52e92b2d 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -101,14 +101,14 @@ class IAXVoIPLink : public VoIPLink { /** * Send out registration */ - virtual void sendRegister(Account *a); + virtual void sendRegister(Account& a); /** * Destroy registration session * @todo Send an IAX_COMMAND_REGREL to force unregistration upstream. * Urgency: low */ - virtual void sendUnregister(Account *a); + virtual void sendUnregister(Account& a); /** * Create a new outgoing call diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index b3ff73e437dbc4bbc4f4954934b09bd1f04d64ff..55c05cff4787b1763fcdf4194b6c6c39e18fc859 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -915,7 +915,7 @@ void SIPAccount::registerVoIPLink() return; try { - link_->sendRegister(this); + link_.sendRegister(*this); } catch (const VoipLinkException &e) { ERROR("%s", e.what()); setRegistrationState(RegistrationState::ERROR_GENERIC); @@ -935,7 +935,7 @@ void SIPAccount::unregisterVoIPLink() return; try { - link_->sendUnregister(this); + link_.sendUnregister(*this); } catch (const VoipLinkException &e) { ERROR("%s", e.what()); } diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h index fe1cc1c67a19a30bc0e0d75491171e24ffccb128..5806af50ddfab849147e52655f2633d820818eda 100644 --- a/daemon/src/sip/siptransport.h +++ b/daemon/src/sip/siptransport.h @@ -2,6 +2,7 @@ * Copyright (C) 2004-2013 Savoir-Faire Linux Inc. * * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * Author: Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 3667186ad46c579c489644a8b4edbc09606d230a..31f11740029e99c2b15951c90846231b79fd406d 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -37,19 +37,19 @@ #include "config.h" #endif +#include "sdp.h" +#include "sipcall.h" #include "sip_utils.h" -#include "array_size.h" -#include "manager.h" -#include "map_utils.h" -#include "logger.h" -#include "sip/sdp.h" -#include "sipcall.h" -#include "eventthread.h" +#include "manager.h" #if HAVE_SDES #include "sdes_negotiator.h" #endif + +#include "logger.h" #include "array_size.h" +#include "map_utils.h" +#include "ip_utils.h" #if HAVE_INSTANT_MESSAGING #include "im/instant_messaging.h" @@ -66,13 +66,13 @@ #include "client/callmanager.h" #include "client/configurationmanager.h" -#include "pjsip/sip_endpoint.h" -#include "pjsip/sip_uri.h" -#include "pjnath.h" +#include <pjsip/sip_endpoint.h> +#include <pjsip/sip_uri.h> +#include <pjnath.h> #ifdef SFL_PRESENCE -#include "pjsip-simple/presence.h" -#include "pjsip-simple/publish.h" +#include <pjsip-simple/presence.h> +#include <pjsip-simple/publish.h> #include "pres_sub_server.h" #endif @@ -735,80 +735,84 @@ bool SIPVoIPLink::getEvent() return handlingEvents_; } -void SIPVoIPLink::sendRegister(Account *a) +std::vector<Call*> +SIPVoIPLink::getCalls(const std::string &account_id) const { - SIPAccount *account = static_cast<SIPAccount*>(a); + std::vector<Call*> calls; + for (const auto & item : sipCallMap_) { + if (item.second->getAccountId() == account_id) + calls.push_back(item.second); + } + return calls; +} - if (!account) - throw VoipLinkException("Account is NULL"); - else if (not account->isEnabled()) { +void +SIPVoIPLink::sendRegister(Account& a) +{ + SIPAccount& account = static_cast<SIPAccount&>(a); + if (not account.isEnabled()) { WARN("Account must be enabled to register, ignoring"); return; } try { - sipTransport->createSipTransport(*account); + sipTransport->createSipTransport(account); } catch (const std::runtime_error &e) { ERROR("%s", e.what()); throw VoipLinkException("Could not create or acquire SIP transport"); } - account->setRegister(true); - account->setRegistrationState(RegistrationState::TRYING); + account.setRegister(true); + account.setRegistrationState(RegistrationState::TRYING); - pjsip_regc *regc = account->getRegistrationInfo(); - - if (pjsip_regc_create(endpt_, (void *) account, ®istration_cb, ®c) != PJ_SUCCESS) + pjsip_regc *regc = nullptr; + if (pjsip_regc_create(endpt_, (void *) &account, ®istration_cb, ®c) != PJ_SUCCESS) throw VoipLinkException("UserAgent: Unable to create regc structure."); - std::string srvUri(account->getServerUri()); - - // std::string address, port; - // findLocalAddressFromUri(srvUri, account->transport_, address, port); + std::string srvUri(account.getServerUri()); pj_str_t pjSrv = pj_str((char*) srvUri.c_str()); // Generate the FROM header - std::string from(account->getFromUri()); + std::string from(account.getFromUri()); pj_str_t pjFrom = pj_str((char*) from.c_str()); // Get the received header - std::string received(account->getReceivedParameter()); + std::string received(account.getReceivedParameter()); // Get the contact header - const pj_str_t pjContact(account->getContactHeader()); + const pj_str_t pjContact(account.getContactHeader()); - if (account->transport_) { - if (not account->getPublishedSameasLocal() or (not received.empty() and received != account->getPublishedAddress())) { - pjsip_host_port *via = account->getViaAddr(); + if (account.transport_) { + if (not account.getPublishedSameasLocal() or (not received.empty() and received != account.getPublishedAddress())) { + pjsip_host_port *via = account.getViaAddr(); DEBUG("Setting VIA sent-by to %.*s:%d", via->host.slen, via->host.ptr, via->port); - if (pjsip_regc_set_via_sent_by(regc, via, account->transport_) != PJ_SUCCESS) + if (pjsip_regc_set_via_sent_by(regc, via, account.transport_) != PJ_SUCCESS) throw VoipLinkException("Unable to set the \"sent-by\" field"); - } else if (account->isStunEnabled()) { - if (pjsip_regc_set_via_sent_by(regc, account->getViaAddr(), account->transport_) != PJ_SUCCESS) + } else if (account.isStunEnabled()) { + if (pjsip_regc_set_via_sent_by(regc, account.getViaAddr(), account.transport_) != PJ_SUCCESS) throw VoipLinkException("Unable to set the \"sent-by\" field"); } } //DEBUG("pjsip_regc_init from:%s, srv:%s, contact:%s", from.c_str(), srvUri.c_str(), std::string(pj_strbuf(&pjContact), pj_strlen(&pjContact)).c_str()); - if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account->getRegistrationExpire()) != PJ_SUCCESS) + if (pjsip_regc_init(regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, account.getRegistrationExpire()) != PJ_SUCCESS) throw VoipLinkException("Unable to initialize account registration structure"); - if (account->hasServiceRoute()) - pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(account->getServiceRoute(), pool_)); + if (account.hasServiceRoute()) + pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(account.getServiceRoute(), pool_)); - pjsip_regc_set_credentials(regc, account->getCredentialCount(), account->getCredInfo()); + pjsip_regc_set_credentials(regc, account.getCredentialCount(), account.getCredInfo()); pjsip_hdr hdr_list; pj_list_init(&hdr_list); - std::string useragent(account->getUserAgentName()); + std::string useragent(account.getUserAgentName()); pj_str_t pJuseragent = pj_str((char*) useragent.c_str()); const pj_str_t STR_USER_AGENT = CONST_PJ_STR("User-Agent"); pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(pool_, &STR_USER_AGENT, &pJuseragent); 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) @@ -830,40 +834,47 @@ void SIPVoIPLink::sendRegister(Account *a) throw VoipLinkException("Unable to send account registration request"); } - account->setRegistrationInfo(regc); + account.setRegistrationInfo(regc); } -void SIPVoIPLink::sendUnregister(Account *a) +void SIPVoIPLink::sendUnregister(Account& a) { - SIPAccount *account = static_cast<SIPAccount *>(a); + SIPAccount& account = static_cast<SIPAccount&>(a); // This may occurs if account failed to register and is in state INVALID - if (!account->isRegistered()) { - account->setRegistrationState(RegistrationState::UNREGISTERED); + if (!account.isRegistered()) { + account.setRegistrationState(RegistrationState::UNREGISTERED); return; } // Make sure to cancel any ongoing timers before unregister - account->stopKeepAliveTimer(); - - pjsip_regc *regc = account->getRegistrationInfo(); + account.stopKeepAliveTimer(); + pjsip_regc *regc = account.getRegistrationInfo(); if (!regc) throw VoipLinkException("Registration structure is NULL"); - pjsip_tx_data *tdata = NULL; - + pjsip_tx_data *tdata = nullptr; if (pjsip_regc_unregister(regc, &tdata) != PJ_SUCCESS) throw VoipLinkException("Unable to unregister sip account"); pj_status_t status; - if ((status = pjsip_regc_send(regc, tdata)) != PJ_SUCCESS) { sip_strerror(status); throw VoipLinkException("Unable to send request to unregister sip account"); } - account->setRegister(false); + account.setRegister(false); + + if (account.transport_) { + if (pj_atomic_get(account.transport_->ref_cnt) > 0) + pjsip_transport_dec_ref(account.transport_); + pjsip_regc_release_transport(regc); // FIXME: are we sure it is the same transport ? + DEBUG("Transport %s has count %d", account.transport_->info, pj_atomic_get(account.transport_->ref_cnt)); + account.transport_ = nullptr; + } + + sipTransport->cleanupTransports(); } void SIPVoIPLink::registerKeepAliveTimer(pj_timer_entry &timer, pj_time_val &delay) @@ -2245,14 +2256,14 @@ void checkNatAddress(pjsip_regc_cbparam ¶m, SIPAccount &account) void registration_cb(pjsip_regc_cbparam *param) { - if (param == NULL) { - ERROR("registration callback parameter is NULL"); + if (!param) { + ERROR("registration callback parameter is null"); return; } SIPAccount *account = static_cast<SIPAccount *>(param->token); - if (account == NULL) { + if (!account) { ERROR("account doesn't exist in registration callback"); return; } @@ -2349,7 +2360,6 @@ void registration_cb(pjsip_regc_cbparam *param) account->setRegistrationStateDetailed(details); account->setRegistrationExpire(param->expiration); } - #undef FAILURE_MESSAGE } diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index a5ab87401eed052d578110a4c91c1e66025feea4..895df50473d6b6aa80d459ad688a4b0dcb52d16a 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -40,23 +40,24 @@ #include "config.h" #endif -#include <map> -#include <mutex> +#include "voiplink.h" +#include "sipaccount.h" +#include "siptransport.h" + +#include "eventthread.h" + +#include <pjsip.h> +#include <pjlib.h> +#include <pjsip_ua.h> +#include <pjlib-util.h> +#include <pjnath.h> +#include <pjnath/stun_config.h> -#include "pjsip.h" -#include "pjlib.h" -#include "pjsip_ua.h" -#include "pjlib-util.h" -#include "pjnath.h" -#include "pjnath/stun_config.h" #ifdef SFL_VIDEO #include <queue> #endif - -#include "sipaccount.h" -#include "voiplink.h" -#include "siptransport.h" -#include "eventthread.h" +#include <map> +#include <mutex> class SIPCall; class SIPAccount; @@ -110,15 +111,18 @@ class SIPVoIPLink : public VoIPLink { AccountMap & getAccounts() { return sipAccountMap_; } + virtual std::vector<Call*> getCalls(const std::string &account_id) const; + /** * Build and send SIP registration request */ - virtual void sendRegister(Account *a); + virtual void sendRegister(Account& a); /** * Build and send SIP unregistration request + * @param destroy_transport If true, attempt to destroy the transport. */ - virtual void sendUnregister(Account *a); + virtual void sendUnregister(Account& a); /** * Register a new keepalive registration timer to this endpoint diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index 91cc64166318c73702200be7e540ff4987b5ffa7..cf689c7e181246e79a1f6caf89b7fcf136421deb 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -36,6 +36,7 @@ #include <stdexcept> #include <string> +#include <vector> class Call; class Account; @@ -65,13 +66,14 @@ class VoIPLink { * Virtual method * Build and send account registration request */ - virtual void sendRegister(Account *a) = 0; + virtual void sendRegister(Account& a) = 0; /** * Virtual method * Build and send account unregistration request + * Underlying ressources are released after unregistration */ - virtual void sendUnregister(Account *a) = 0; + virtual void sendUnregister(Account& a) = 0; /** * Place a new call @@ -83,6 +85,12 @@ class VoIPLink { const std::string &toUrl, const std::string &account_id) = 0; + /** + * Virtual method + * Returns calls involving this account. + */ + virtual std::vector<Call*> getCalls(const std::string &account_id) const = 0; + /** * Answer the call * @param c The call