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