LCOV - code coverage report
Current view: top level - foo/src/sip - pres_sub_client.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 274 0.0 %
Date: 2025-12-18 10:07:43 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2012, 2013 LOTES TM LLC
       3             :  *  Author : Andrey Loukhnov <aol.nnov@gmail.com>
       4             :  *
       5             :  *  This file is a part of pult5-voip
       6             :  *
       7             :  *  pult5-voip is free software; you can redistribute it and/or modify
       8             :  *  it under the terms of the GNU General Public License as published by
       9             :  *  the Free Software Foundation; either version 3 of the License, or
      10             :  *  (at your option) any later version.
      11             :  *
      12             :  *  pult5-voip is distributed in the hope that it will be useful,
      13             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  *  GNU General Public License for more details.
      16             :  *
      17             :  *  You should have received a copy of the GNU General Public License
      18             :  *  along with this programm. If not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <pj/log.h>
      22             : #include <pj/rand.h>
      23             : #include <pjsip/sip_module.h>
      24             : #include <pjsip/sip_types.h>
      25             : #include <pjsip/sip_event.h>
      26             : #include <pjsip/sip_transaction.h>
      27             : #include <pjsip/sip_dialog.h>
      28             : #include <pjsip/sip_endpoint.h>
      29             : #include <string>
      30             : #include <sstream>
      31             : #include <thread>
      32             : #include <pj/pool.h>
      33             : #include <pjsip/sip_ua_layer.h>
      34             : #include <pjsip-simple/evsub.h>
      35             : #include <unistd.h>
      36             : 
      37             : #include "pres_sub_client.h"
      38             : #include "sip/sipaccount.h"
      39             : #include "sip/sippresence.h"
      40             : #include "sip/sipvoiplink.h"
      41             : #include "connectivity/sip_utils.h"
      42             : #include "manager.h"
      43             : #include "client/ring_signal.h"
      44             : 
      45             : #include "logger.h"
      46             : 
      47             : #define PRES_TIMER 300 // 5min
      48             : 
      49             : namespace jami {
      50             : 
      51             : using sip_utils::CONST_PJ_STR;
      52             : 
      53             : int PresSubClient::modId_ = 0; // used to extract data structure from event_subscription
      54             : 
      55             : void
      56           0 : PresSubClient::pres_client_timer_cb(pj_timer_heap_t* /*th*/, pj_timer_entry* entry)
      57             : {
      58           0 :     PresSubClient* c = (PresSubClient*) entry->user_data;
      59           0 :     JAMI_DBG("timeout for %.*s", (int) c->getURI().size(), c->getURI().data());
      60           0 : }
      61             : 
      62             : /* Callback called when *client* subscription state has changed. */
      63             : void
      64           0 : PresSubClient::pres_client_evsub_on_state(pjsip_evsub* sub, pjsip_event* event)
      65             : {
      66             :     PJ_UNUSED_ARG(event);
      67             : 
      68           0 :     PresSubClient* pres_client = (PresSubClient*) pjsip_evsub_get_mod_data(sub, modId_);
      69             :     /* No need to pres->lock() here since the client has a locked dialog*/
      70             : 
      71           0 :     if (!pres_client) {
      72           0 :         JAMI_WARN("pres_client not found");
      73           0 :         return;
      74             :     }
      75             : 
      76           0 :     JAMI_DBG("Subscription for pres_client '%.*s' is '%s'",
      77             :              (int) pres_client->getURI().size(),
      78             :              pres_client->getURI().data(),
      79             :              pjsip_evsub_get_state_name(sub) ? pjsip_evsub_get_state_name(sub) : "null");
      80             : 
      81           0 :     pjsip_evsub_state state = pjsip_evsub_get_state(sub);
      82             : 
      83           0 :     SIPPresence* pres = pres_client->getPresence();
      84             : 
      85           0 :     if (state == PJSIP_EVSUB_STATE_ACCEPTED) {
      86           0 :         pres_client->enable(true);
      87           0 :         emitSignal<libjami::PresenceSignal::SubscriptionStateChanged>(pres->getAccount()->getAccountID(),
      88           0 :                                                                       std::string(pres_client->getURI()),
      89             :                                                                       PJ_TRUE);
      90             : 
      91           0 :         pres->getAccount()->supportPresence(PRESENCE_FUNCTION_SUBSCRIBE, true);
      92             : 
      93           0 :     } else if (state == PJSIP_EVSUB_STATE_TERMINATED) {
      94           0 :         int resub_delay = -1;
      95           0 :         pj_strdup_with_null(pres_client->pool_, &pres_client->term_reason_, pjsip_evsub_get_termination_reason(sub));
      96             : 
      97           0 :         emitSignal<libjami::PresenceSignal::SubscriptionStateChanged>(pres->getAccount()->getAccountID(),
      98           0 :                                                                       std::string(pres_client->getURI()),
      99             :                                                                       PJ_FALSE);
     100             : 
     101           0 :         pres_client->term_code_ = 200;
     102             : 
     103             :         /* Determine whether to resubscribe automatically */
     104           0 :         if (event && event->type == PJSIP_EVENT_TSX_STATE) {
     105           0 :             const pjsip_transaction* tsx = event->body.tsx_state.tsx;
     106             : 
     107           0 :             if (pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method) == 0) {
     108           0 :                 pres_client->term_code_ = tsx->status_code;
     109           0 :                 std::ostringstream os;
     110           0 :                 os << pres_client->term_code_;
     111           0 :                 const std::string error = os.str() + "/" + sip_utils::as_view(pres_client->term_reason_);
     112             : 
     113           0 :                 std::string msg;
     114           0 :                 bool subscribe_allowed = PJ_FALSE;
     115             : 
     116           0 :                 switch (tsx->status_code) {
     117           0 :                 case PJSIP_SC_CALL_TSX_DOES_NOT_EXIST:
     118             :                     /* 481: we refreshed too late? resubscribe
     119             :                      * immediately.
     120             :                      */
     121             :                     /* But this must only happen when the 481 is received
     122             :                      * on subscription refresh request. We MUST NOT try to
     123             :                      * resubscribe automatically if the 481 is received
     124             :                      * on the initial SUBSCRIBE (if server returns this
     125             :                      * response for some reason).
     126             :                      */
     127           0 :                     if (pres_client->dlg_->remote.contact)
     128           0 :                         resub_delay = 500;
     129           0 :                     msg = "Bad subscribe refresh.";
     130           0 :                     subscribe_allowed = PJ_TRUE;
     131           0 :                     break;
     132             : 
     133           0 :                 case PJSIP_SC_NOT_FOUND:
     134           0 :                     msg = "Subscribe context not set for this buddy.";
     135           0 :                     subscribe_allowed = PJ_TRUE;
     136           0 :                     break;
     137             : 
     138           0 :                 case PJSIP_SC_FORBIDDEN:
     139           0 :                     msg = "Subscribe not allowed for this buddy.";
     140           0 :                     subscribe_allowed = PJ_TRUE;
     141           0 :                     break;
     142             : 
     143           0 :                 case PJSIP_SC_PRECONDITION_FAILURE:
     144           0 :                     msg = "Wrong server.";
     145           0 :                     break;
     146             :                 }
     147             : 
     148             :                 /*  report error:
     149             :                  *  1) send a signal through DBus
     150             :                  *  2) change the support field in the account schema if the pres_sub's server
     151             :                  *  is the same as the account's server
     152             :                  */
     153           0 :                 emitSignal<libjami::PresenceSignal::ServerError>(pres_client->getPresence()->getAccount()->getAccountID(),
     154             :                                                                  error,
     155             :                                                                  msg);
     156             : 
     157           0 :                 auto account_host = sip_utils::as_view(*pj_gethostname());
     158           0 :                 auto sub_host = sip_utils::getHostFromUri(pres_client->getURI());
     159             : 
     160           0 :                 if (not subscribe_allowed and account_host == sub_host)
     161           0 :                     pres_client->getPresence()->getAccount()->supportPresence(PRESENCE_FUNCTION_SUBSCRIBE, false);
     162             : 
     163           0 :             } else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method) == 0) {
     164           0 :                 if (pres_client->isTermReason("deactivated") || pres_client->isTermReason("timeout")) {
     165             :                     /* deactivated: The subscription has been terminated,
     166             :                      * but the subscriber SHOULD retry immediately with
     167             :                      * a new subscription.
     168             :                      */
     169             :                     /* timeout: The subscription has been terminated
     170             :                      * because it was not refreshed before it expired.
     171             :                      * Clients MAY re-subscribe immediately. The
     172             :                      * "retry-after" parameter has no semantics for
     173             :                      * "timeout".
     174             :                      */
     175           0 :                     resub_delay = 500;
     176           0 :                 } else if (pres_client->isTermReason("probation") || pres_client->isTermReason("giveup")) {
     177             :                     /* probation: The subscription has been terminated,
     178             :                      * but the client SHOULD retry at some later time.
     179             :                      * If a "retry-after" parameter is also present, the
     180             :                      * client SHOULD wait at least the number of seconds
     181             :                      * specified by that parameter before attempting to re-
     182             :                      * subscribe.
     183             :                      */
     184             :                     /* giveup: The subscription has been terminated because
     185             :                      * the notifier was unable to obtain authorization in a
     186             :                      * timely fashion.  If a "retry-after" parameter is
     187             :                      * also present, the client SHOULD wait at least the
     188             :                      * number of seconds specified by that parameter before
     189             :                      * attempting to re-subscribe; otherwise, the client
     190             :                      * MAY retry immediately, but will likely get put back
     191             :                      * into pending state.
     192             :                      */
     193             :                     const pjsip_sub_state_hdr* sub_hdr;
     194           0 :                     constexpr pj_str_t sub_state = CONST_PJ_STR("Subscription-State");
     195             :                     const pjsip_msg* msg;
     196             : 
     197           0 :                     msg = event->body.tsx_state.src.rdata->msg_info.msg;
     198           0 :                     sub_hdr = (const pjsip_sub_state_hdr*) pjsip_msg_find_hdr_by_name(msg, &sub_state, NULL);
     199             : 
     200           0 :                     if (sub_hdr && sub_hdr->retry_after > 0)
     201           0 :                         resub_delay = sub_hdr->retry_after * 1000;
     202             :                 }
     203             :             }
     204             :         }
     205             : 
     206             :         /* For other cases of subscription termination, if resubscribe
     207             :          * timer is not set, schedule with default expiration (plus minus
     208             :          * some random value, to avoid sending SUBSCRIBEs all at once)
     209             :          */
     210           0 :         if (resub_delay == -1) {
     211           0 :             resub_delay = PRES_TIMER * 1000;
     212             :         }
     213             : 
     214           0 :         pres_client->sub_ = sub;
     215           0 :         pres_client->rescheduleTimer(PJ_TRUE, resub_delay);
     216             : 
     217             :     } else { // state==ACTIVE ......
     218             :         // This will clear the last termination code/reason
     219           0 :         pres_client->term_code_ = 0;
     220           0 :         pres_client->term_reason_.ptr = NULL;
     221             :     }
     222             : 
     223             :     /* Clear subscription */
     224           0 :     if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
     225           0 :         pjsip_evsub_terminate(pres_client->sub_, PJ_FALSE); // = NULL;
     226           0 :         pres_client->status_.info_cnt = 0;
     227           0 :         pres_client->dlg_ = NULL;
     228           0 :         pres_client->rescheduleTimer(PJ_FALSE, 0);
     229           0 :         pjsip_evsub_set_mod_data(sub, modId_, NULL);
     230             : 
     231           0 :         pres_client->enable(false);
     232             :     }
     233             : }
     234             : 
     235             : /* Callback when transaction state has changed. */
     236             : void
     237           0 : PresSubClient::pres_client_evsub_on_tsx_state(pjsip_evsub* sub, pjsip_transaction* tsx, pjsip_event* event)
     238             : {
     239             :     PresSubClient* pres_client;
     240             :     pjsip_contact_hdr* contact_hdr;
     241             : 
     242           0 :     pres_client = (PresSubClient*) pjsip_evsub_get_mod_data(sub, modId_);
     243             :     /* No need to pres->lock() here since the client has a locked dialog*/
     244             : 
     245           0 :     if (!pres_client) {
     246           0 :         JAMI_WARN("Unable to find pres_client.");
     247           0 :         return;
     248             :     }
     249             : 
     250             :     /* We only use this to update pres_client's Contact, when it's not
     251             :      * set.
     252             :      */
     253           0 :     if (pres_client->contact_.slen != 0) {
     254             :         /* Contact already set */
     255           0 :         return;
     256             :     }
     257             : 
     258             :     /* Only care about 2xx response to outgoing SUBSCRIBE */
     259           0 :     if (tsx->status_code / 100 != 2 || tsx->role != PJSIP_UAC_ROLE || event->type != PJSIP_EVENT_RX_MSG
     260           0 :         || pjsip_method_cmp(&tsx->method, pjsip_get_subscribe_method()) != 0) {
     261           0 :         return;
     262             :     }
     263             : 
     264             :     /* Find contact header. */
     265           0 :     contact_hdr = (pjsip_contact_hdr*) pjsip_msg_find_hdr(event->body.rx_msg.rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
     266             : 
     267           0 :     if (!contact_hdr || !contact_hdr->uri) {
     268           0 :         return;
     269             :     }
     270             : 
     271           0 :     pres_client->contact_.ptr = (char*) pj_pool_alloc(pres_client->pool_, PJSIP_MAX_URL_SIZE);
     272           0 :     pres_client->contact_.slen = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR,
     273           0 :                                                  contact_hdr->uri,
     274             :                                                  pres_client->contact_.ptr,
     275             :                                                  PJSIP_MAX_URL_SIZE);
     276             : 
     277           0 :     if (pres_client->contact_.slen < 0)
     278           0 :         pres_client->contact_.slen = 0;
     279             : }
     280             : 
     281             : /* Callback called when we receive NOTIFY */
     282             : void
     283           0 : PresSubClient::pres_client_evsub_on_rx_notify(pjsip_evsub* sub,
     284             :                                               pjsip_rx_data* rdata,
     285             :                                               int* p_st_code,
     286             :                                               pj_str_t** p_st_text,
     287             :                                               pjsip_hdr* res_hdr,
     288             :                                               pjsip_msg_body** p_body)
     289             : {
     290           0 :     PresSubClient* pres_client = (PresSubClient*) pjsip_evsub_get_mod_data(sub, modId_);
     291             : 
     292           0 :     if (!pres_client) {
     293           0 :         JAMI_WARN("Unable to find pres_client from ev_sub.");
     294           0 :         return;
     295             :     }
     296             :     /* No need to pres->lock() here since the client has a locked dialog*/
     297             : 
     298           0 :     pjsip_pres_get_status(sub, &pres_client->status_);
     299           0 :     pres_client->reportPresence();
     300             : 
     301             :     /* The default is to send 200 response to NOTIFY.
     302             :      * Just leave it there.
     303             :      */
     304             :     PJ_UNUSED_ARG(rdata);
     305             :     PJ_UNUSED_ARG(p_st_code);
     306             :     PJ_UNUSED_ARG(p_st_text);
     307             :     PJ_UNUSED_ARG(res_hdr);
     308             :     PJ_UNUSED_ARG(p_body);
     309             : }
     310             : 
     311           0 : PresSubClient::PresSubClient(const std::string& uri, SIPPresence* pres)
     312           0 :     : pres_(pres)
     313           0 :     , uri_ {0, 0}
     314           0 :     , contact_ {0, 0}
     315           0 :     , display_()
     316           0 :     , dlg_(NULL)
     317           0 :     , monitored_(false)
     318           0 :     , name_()
     319           0 :     , cp_()
     320           0 :     , pool_(0)
     321           0 :     , status_()
     322           0 :     , sub_(NULL)
     323           0 :     , term_code_(0)
     324           0 :     , term_reason_()
     325           0 :     , timer_()
     326           0 :     , user_data_(NULL)
     327           0 :     , lock_count_(0)
     328           0 :     , lock_flag_(0)
     329             : {
     330           0 :     pj_caching_pool_init(&cp_, &pj_pool_factory_default_policy, 0);
     331           0 :     pool_ = pj_pool_create(&cp_.factory, "Pres_sub_client", 512, 512, NULL);
     332           0 :     uri_ = pj_strdup3(pool_, uri.c_str());
     333           0 :     contact_ = pj_strdup3(pool_, pres_->getAccount()->getFromUri().c_str());
     334           0 : }
     335             : 
     336           0 : PresSubClient::~PresSubClient()
     337             : {
     338           0 :     JAMI_DBG("Destroying pres_client object with uri %.*s", (int) uri_.slen, uri_.ptr);
     339           0 :     rescheduleTimer(PJ_FALSE, 0);
     340           0 :     unsubscribe();
     341           0 :     pj_pool_release(pool_);
     342           0 : }
     343             : 
     344             : bool
     345           0 : PresSubClient::isSubscribed()
     346             : {
     347           0 :     return monitored_;
     348             : }
     349             : 
     350             : std::string_view
     351           0 : PresSubClient::getURI()
     352             : {
     353           0 :     return {uri_.ptr, (size_t) uri_.slen};
     354             : }
     355             : 
     356             : SIPPresence*
     357           0 : PresSubClient::getPresence()
     358             : {
     359           0 :     return pres_;
     360             : }
     361             : 
     362             : bool
     363           0 : PresSubClient::isPresent()
     364             : {
     365           0 :     return status_.info[0].basic_open;
     366             : }
     367             : 
     368             : std::string_view
     369           0 : PresSubClient::getLineStatus()
     370             : {
     371           0 :     return {status_.info[0].rpid.note.ptr, (size_t) status_.info[0].rpid.note.slen};
     372             : }
     373             : 
     374             : bool
     375           0 : PresSubClient::isTermReason(const std::string& reason)
     376             : {
     377           0 :     const std::string_view myReason(term_reason_.ptr, (size_t) term_reason_.slen);
     378           0 :     return not myReason.compare(reason);
     379             : }
     380             : 
     381             : void
     382           0 : PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
     383             : {
     384           0 :     if (timer_.id) {
     385           0 :         pjsip_endpt_cancel_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_);
     386           0 :         timer_.id = PJ_FALSE;
     387             :     }
     388             : 
     389           0 :     if (reschedule) {
     390             :         pj_time_val delay;
     391             : 
     392           0 :         JAMI_WARN("pres_client  %.*s will resubscribe in %u ms (reason: %.*s)",
     393             :                   (int) uri_.slen,
     394             :                   uri_.ptr,
     395             :                   msec,
     396             :                   (int) term_reason_.slen,
     397             :                   term_reason_.ptr);
     398           0 :         pj_timer_entry_init(&timer_, 0, this, &pres_client_timer_cb);
     399           0 :         delay.sec = 0;
     400           0 :         delay.msec = msec;
     401           0 :         pj_time_val_normalize(&delay);
     402             : 
     403           0 :         if (pjsip_endpt_schedule_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
     404           0 :             timer_.id = PJ_TRUE;
     405             :         }
     406             :     }
     407           0 : }
     408             : 
     409             : void
     410           0 : PresSubClient::enable(bool flag)
     411             : {
     412           0 :     JAMI_DBG("pres_client %.*s is %s monitored.", (int) getURI().size(), getURI().data(), flag ? "" : "NOT");
     413           0 :     if (flag and not monitored_)
     414           0 :         pres_->addPresSubClient(this);
     415           0 :     monitored_ = flag;
     416           0 : }
     417             : 
     418             : void
     419           0 : PresSubClient::reportPresence()
     420             : {
     421             :     /* callback*/
     422           0 :     pres_->reportPresSubClientNotification(getURI(), &status_);
     423           0 : }
     424             : 
     425             : bool
     426           0 : PresSubClient::lock()
     427             : {
     428             :     unsigned i;
     429             : 
     430           0 :     for (i = 0; i < 50; i++) {
     431           0 :         if (not pres_->tryLock()) {
     432             :             // FIXME: i/10 in ms, sure!?
     433           0 :             std::this_thread::sleep_for(std::chrono::milliseconds(i / 10));
     434           0 :             continue;
     435             :         }
     436           0 :         lock_flag_ = PRESENCE_LOCK_FLAG;
     437             : 
     438           0 :         if (dlg_ == NULL) {
     439           0 :             pres_->unlock();
     440           0 :             return true;
     441             :         }
     442             : 
     443           0 :         if (pjsip_dlg_try_inc_lock(dlg_) != PJ_SUCCESS) {
     444           0 :             lock_flag_ = 0;
     445           0 :             pres_->unlock();
     446             :             // FIXME: i/10 in ms, sure!?
     447           0 :             std::this_thread::sleep_for(std::chrono::milliseconds(i / 10));
     448           0 :             continue;
     449             :         }
     450             : 
     451           0 :         lock_flag_ = PRESENCE_CLIENT_LOCK_FLAG;
     452           0 :         pres_->unlock();
     453             :     }
     454             : 
     455           0 :     if (lock_flag_ == 0) {
     456           0 :         JAMI_DBG("pres_client failed to lock : timeout");
     457           0 :         return false;
     458             :     }
     459           0 :     return true;
     460             : }
     461             : 
     462             : void
     463           0 : PresSubClient::unlock()
     464             : {
     465           0 :     if (lock_flag_ & PRESENCE_CLIENT_LOCK_FLAG)
     466           0 :         pjsip_dlg_dec_lock(dlg_);
     467             : 
     468           0 :     if (lock_flag_ & PRESENCE_LOCK_FLAG)
     469           0 :         pres_->unlock();
     470           0 : }
     471             : 
     472             : bool
     473           0 : PresSubClient::unsubscribe()
     474             : {
     475           0 :     if (not lock())
     476           0 :         return false;
     477             : 
     478           0 :     monitored_ = false;
     479             : 
     480             :     pjsip_tx_data* tdata;
     481             :     pj_status_t retStatus;
     482             : 
     483           0 :     if (sub_ == NULL or dlg_ == NULL) {
     484           0 :         JAMI_WARN("PresSubClient already unsubscribed.");
     485           0 :         unlock();
     486           0 :         return false;
     487             :     }
     488             : 
     489           0 :     if (pjsip_evsub_get_state(sub_) == PJSIP_EVSUB_STATE_TERMINATED) {
     490           0 :         JAMI_WARN("pres_client already unsubscribed sub=TERMINATED.");
     491           0 :         sub_ = NULL;
     492           0 :         unlock();
     493           0 :         return false;
     494             :     }
     495             : 
     496             :     /* Unsubscribe means send a subscribe with timeout=0s*/
     497           0 :     JAMI_WARN("pres_client %.*s: unsubscribing..", (int) uri_.slen, uri_.ptr);
     498           0 :     retStatus = pjsip_pres_initiate(sub_, 0, &tdata);
     499             : 
     500           0 :     if (retStatus == PJ_SUCCESS) {
     501           0 :         pres_->fillDoc(tdata, NULL);
     502           0 :         retStatus = pjsip_pres_send_request(sub_, tdata);
     503             :     }
     504             : 
     505           0 :     if (retStatus != PJ_SUCCESS and sub_) {
     506           0 :         pjsip_pres_terminate(sub_, PJ_FALSE);
     507           0 :         sub_ = NULL;
     508           0 :         JAMI_WARN("Unable to unsubscribe presence (%d)", retStatus);
     509           0 :         unlock();
     510           0 :         return false;
     511             :     }
     512             : 
     513             :     // pjsip_evsub_set_mod_data(sub_, modId_, NULL);   // Not interested with further events
     514             : 
     515           0 :     unlock();
     516           0 :     return true;
     517             : }
     518             : 
     519             : bool
     520           0 : PresSubClient::subscribe()
     521             : {
     522           0 :     if (sub_ and dlg_) { // do not bother if already subscribed
     523           0 :         pjsip_evsub_terminate(sub_, PJ_FALSE);
     524           0 :         JAMI_DBG("PreseSubClient %.*s: already subscribed. Refresh it.", (int) uri_.slen, uri_.ptr);
     525             :     }
     526             : 
     527             :     // subscribe
     528             :     pjsip_evsub_user pres_callback;
     529             :     pjsip_tx_data* tdata;
     530             :     pj_status_t status;
     531             : 
     532             :     /* Event subscription callback. */
     533           0 :     pj_bzero(&pres_callback, sizeof(pres_callback));
     534           0 :     pres_callback.on_evsub_state = &pres_client_evsub_on_state;
     535           0 :     pres_callback.on_tsx_state = &pres_client_evsub_on_tsx_state;
     536           0 :     pres_callback.on_rx_notify = &pres_client_evsub_on_rx_notify;
     537             : 
     538           0 :     SIPAccount* acc = pres_->getAccount();
     539           0 :     JAMI_DBG("PresSubClient %.*s: subscribing ", (int) uri_.slen, uri_.ptr);
     540             : 
     541             :     /* Create UAC dialog */
     542           0 :     pj_str_t from = pj_strdup3(pool_, acc->getFromUri().c_str());
     543           0 :     status = pjsip_dlg_create_uac(pjsip_ua_instance(), &from, &contact_, &uri_, NULL, &dlg_);
     544             : 
     545           0 :     if (status != PJ_SUCCESS) {
     546           0 :         JAMI_ERR("Unable to create dialog \n");
     547           0 :         return false;
     548             :     }
     549             : 
     550             :     /* Add credential for auth. */
     551           0 :     if (acc->hasCredentials()
     552           0 :         and pjsip_auth_clt_set_credentials(&dlg_->auth_sess, acc->getCredentialCount(), acc->getCredInfo())
     553             :                 != PJ_SUCCESS) {
     554           0 :         JAMI_ERR("Unable to initialize credentials for subscribe session authentication");
     555             :     }
     556             : 
     557             :     /* Increment the dialog's lock otherwise when presence session creation
     558             :      * fails the dialog will be destroyed prematurely.
     559             :      */
     560           0 :     pjsip_dlg_inc_lock(dlg_);
     561             : 
     562           0 :     status = pjsip_pres_create_uac(dlg_, &pres_callback, PJSIP_EVSUB_NO_EVENT_ID, &sub_);
     563             : 
     564           0 :     if (status != PJ_SUCCESS) {
     565           0 :         sub_ = NULL;
     566           0 :         JAMI_WARN("Unable to create presence client (%d)", status);
     567             : 
     568             :         /* This should destroy the dialog since there's no session
     569             :          * referencing it
     570             :          */
     571           0 :         if (dlg_) {
     572           0 :             pjsip_dlg_dec_lock(dlg_);
     573             :         }
     574             : 
     575           0 :         return false;
     576             :     }
     577             : 
     578             :     /* Add credential for authentication */
     579           0 :     if (acc->hasCredentials()
     580           0 :         and pjsip_auth_clt_set_credentials(&dlg_->auth_sess, acc->getCredentialCount(), acc->getCredInfo())
     581             :                 != PJ_SUCCESS) {
     582           0 :         JAMI_ERR("Unable to initialize credentials for invite session authentication");
     583           0 :         return false;
     584             :     }
     585             : 
     586             :     /* Set route-set */
     587           0 :     pjsip_regc* regc = acc->getRegistrationInfo();
     588           0 :     if (regc and acc->hasServiceRoute())
     589           0 :         pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(acc->getServiceRoute(), pres_->getPool()));
     590             : 
     591             :     // attach the client data to the sub
     592           0 :     pjsip_evsub_set_mod_data(sub_, modId_, this);
     593             : 
     594           0 :     status = pjsip_pres_initiate(sub_, -1, &tdata);
     595           0 :     if (status != PJ_SUCCESS) {
     596           0 :         if (dlg_)
     597           0 :             pjsip_dlg_dec_lock(dlg_);
     598           0 :         if (sub_)
     599           0 :             pjsip_pres_terminate(sub_, PJ_FALSE);
     600           0 :         sub_ = NULL;
     601           0 :         JAMI_WARN("Unable to create initial SUBSCRIBE (%d)", status);
     602           0 :         return false;
     603             :     }
     604             : 
     605             :     //    pjsua_process_msg_data(tdata, NULL);
     606             : 
     607           0 :     status = pjsip_pres_send_request(sub_, tdata);
     608             : 
     609           0 :     if (status != PJ_SUCCESS) {
     610           0 :         if (dlg_)
     611           0 :             pjsip_dlg_dec_lock(dlg_);
     612           0 :         if (sub_)
     613           0 :             pjsip_pres_terminate(sub_, PJ_FALSE);
     614           0 :         sub_ = NULL;
     615           0 :         JAMI_WARN("Unable to send initial SUBSCRIBE (%d)", status);
     616           0 :         return false;
     617             :     }
     618             : 
     619           0 :     pjsip_dlg_dec_lock(dlg_);
     620           0 :     return true;
     621             : }
     622             : 
     623             : bool
     624           0 : PresSubClient::match(PresSubClient* b)
     625             : {
     626           0 :     return (b->getURI() == getURI());
     627             : }
     628             : 
     629             : } // namespace jami

Generated by: LCOV version 1.14