blob: b3205cc59ce9d46f925bb4767da4056abd5eb77f [file] [log] [blame]
Benny Prijono834aee32006-02-19 01:38:06 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
Benny Prijono4f9f64e2006-02-27 00:00:30 +000019#include <pjsua-lib/pjsua.h>
Benny Prijonoeebe9af2006-06-13 22:57:13 +000020#include <pjsua-lib/pjsua_internal.h>
Benny Prijono834aee32006-02-19 01:38:06 +000021
Benny Prijono834aee32006-02-19 01:38:06 +000022
23#define THIS_FILE "pjsua_pres.c"
24
25
Benny Prijonoeebe9af2006-06-13 22:57:13 +000026/*
27 * Get total number of buddies.
28 */
29PJ_DEF(unsigned) pjsua_get_buddy_count(void)
30{
31 return pjsua_var.buddy_cnt;
32}
Benny Prijono834aee32006-02-19 01:38:06 +000033
Benny Prijonoeebe9af2006-06-13 22:57:13 +000034
35/*
36 * Check if buddy ID is valid.
37 */
38PJ_DEF(pj_bool_t) pjsua_buddy_is_valid(pjsua_buddy_id buddy_id)
39{
40 return buddy_id>=0 && buddy_id<PJ_ARRAY_SIZE(pjsua_var.buddy) &&
41 pjsua_var.buddy[buddy_id].uri.slen != 0;
42}
43
44
45/*
46 * Enum buddy IDs.
47 */
48PJ_DEF(pj_status_t) pjsua_enum_buddies( pjsua_buddy_id ids[],
49 unsigned *count)
50{
51 unsigned i, c;
52
53 PJ_ASSERT_RETURN(ids && count, PJ_EINVAL);
54
55 PJSUA_LOCK();
56
57 for (i=0, c=0; c<*count && i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
58 if (!pjsua_var.buddy[i].uri.slen)
59 continue;
60 ids[c] = i;
61 ++c;
62 }
63
64 *count = c;
65
66 PJSUA_UNLOCK();
67
68 return PJ_SUCCESS;
69
70}
71
72
73/*
74 * Get detailed buddy info.
75 */
76PJ_DEF(pj_status_t) pjsua_buddy_get_info( pjsua_buddy_id buddy_id,
77 pjsua_buddy_info *info)
78{
79 int total=0;
80 pjsua_buddy *buddy;
81
82 PJ_ASSERT_RETURN(buddy_id>=0 &&
83 buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy),
84 PJ_EINVAL);
85
86 PJSUA_LOCK();
87
Benny Prijonoac623b32006-07-03 15:19:31 +000088 pj_bzero(info, sizeof(pjsua_buddy_info));
Benny Prijonoeebe9af2006-06-13 22:57:13 +000089
90 buddy = &pjsua_var.buddy[buddy_id];
91 info->id = buddy->index;
92 if (pjsua_var.buddy[buddy_id].uri.slen == 0) {
93 PJSUA_UNLOCK();
94 return PJ_SUCCESS;
95 }
96
97 /* uri */
98 info->uri.ptr = info->buf_ + total;
99 pj_strncpy(&info->uri, &buddy->uri, sizeof(info->buf_)-total);
100 total += info->uri.slen;
101
102 /* contact */
103 info->contact.ptr = info->buf_ + total;
104 pj_strncpy(&info->contact, &buddy->contact, sizeof(info->buf_)-total);
105 total += info->contact.slen;
106
107 /* status and status text */
108 if (buddy->sub == NULL || buddy->status.info_cnt==0) {
109 info->status = PJSUA_BUDDY_STATUS_UNKNOWN;
110 info->status_text = pj_str("?");
111 } else if (pjsua_var.buddy[buddy_id].status.info[0].basic_open) {
112 info->status = PJSUA_BUDDY_STATUS_ONLINE;
113 info->status_text = pj_str("Online");
114 } else {
115 info->status = PJSUA_BUDDY_STATUS_OFFLINE;
116 info->status_text = pj_str("Offline");
117 }
118
119 /* monitor pres */
120 info->monitor_pres = buddy->monitor;
121
122 PJSUA_UNLOCK();
123 return PJ_SUCCESS;
124}
125
126
127/*
128 * Reset buddy descriptor.
129 */
130static void reset_buddy(pjsua_buddy_id id)
131{
Benny Prijonoac623b32006-07-03 15:19:31 +0000132 pj_bzero(&pjsua_var.buddy[id], sizeof(pjsua_var.buddy[id]));
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000133 pjsua_var.buddy[id].index = id;
134}
135
136
137/*
138 * Add new buddy.
139 */
140PJ_DEF(pj_status_t) pjsua_buddy_add( const pjsua_buddy_config *cfg,
141 pjsua_buddy_id *p_buddy_id)
142{
143 pjsip_name_addr *url;
144 pjsip_sip_uri *sip_uri;
145 int index;
146 pj_str_t tmp;
147
148 PJ_ASSERT_RETURN(pjsua_var.buddy_cnt <=
149 PJ_ARRAY_SIZE(pjsua_var.buddy),
150 PJ_ETOOMANY);
151
152 PJSUA_LOCK();
153
154 /* Find empty slot */
155 for (index=0; index<PJ_ARRAY_SIZE(pjsua_var.buddy); ++index) {
156 if (pjsua_var.buddy[index].uri.slen == 0)
157 break;
158 }
159
160 /* Expect to find an empty slot */
161 if (index == PJ_ARRAY_SIZE(pjsua_var.buddy)) {
162 PJSUA_UNLOCK();
163 /* This shouldn't happen */
164 pj_assert(!"index < PJ_ARRAY_SIZE(pjsua_var.buddy)");
165 return PJ_ETOOMANY;
166 }
167
168
169 /* Get name and display name for buddy */
170 pj_strdup_with_null(pjsua_var.pool, &tmp, &cfg->uri);
171 url = (pjsip_name_addr*)pjsip_parse_uri(pjsua_var.pool, tmp.ptr, tmp.slen,
172 PJSIP_PARSE_URI_AS_NAMEADDR);
173
174 if (url == NULL) {
175 pjsua_perror(THIS_FILE, "Unable to add buddy", PJSIP_EINVALIDURI);
176 PJSUA_UNLOCK();
177 return PJSIP_EINVALIDURI;
178 }
179
180 /* Reset buddy, to make sure everything is cleared with default
181 * values
182 */
183 reset_buddy(index);
184
185 /* Save URI */
186 pjsua_var.buddy[index].uri = tmp;
187
188 sip_uri = (pjsip_sip_uri*) url->uri;
189 pjsua_var.buddy[index].name = sip_uri->user;
190 pjsua_var.buddy[index].display = url->display;
191 pjsua_var.buddy[index].host = sip_uri->host;
192 pjsua_var.buddy[index].port = sip_uri->port;
193 pjsua_var.buddy[index].monitor = cfg->subscribe;
194 if (pjsua_var.buddy[index].port == 0)
195 pjsua_var.buddy[index].port = 5060;
196
197 if (p_buddy_id)
198 *p_buddy_id = index;
199
200 pjsua_var.buddy_cnt++;
201
202 pjsua_buddy_subscribe_pres(index, cfg->subscribe);
203
204 PJSUA_UNLOCK();
205
206 return PJ_SUCCESS;
207}
208
209
210/*
211 * Delete buddy.
212 */
213PJ_DEF(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id)
214{
215 PJ_ASSERT_RETURN(buddy_id>=0 &&
216 buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy),
217 PJ_EINVAL);
218
219 PJSUA_LOCK();
220
221 if (pjsua_var.buddy[buddy_id].uri.slen == 0) {
222 PJSUA_UNLOCK();
223 return PJ_SUCCESS;
224 }
225
226 /* Unsubscribe presence */
227 pjsua_buddy_subscribe_pres(buddy_id, PJ_FALSE);
228
229 /* Remove buddy */
230 pjsua_var.buddy[buddy_id].uri.slen = 0;
231 pjsua_var.buddy_cnt--;
232
233 /* Reset buddy struct */
234 reset_buddy(buddy_id);
235
236 PJSUA_UNLOCK();
237 return PJ_SUCCESS;
238}
239
240
241/*
242 * Enable/disable buddy's presence monitoring.
243 */
244PJ_DEF(pj_status_t) pjsua_buddy_subscribe_pres( pjsua_buddy_id buddy_id,
245 pj_bool_t subscribe)
246{
247 pjsua_buddy *buddy;
248
249 PJ_ASSERT_RETURN(buddy_id>=0 &&
250 buddy_id<(int)PJ_ARRAY_SIZE(pjsua_var.buddy),
251 PJ_EINVAL);
252
253 PJSUA_LOCK();
254
255 buddy = &pjsua_var.buddy[buddy_id];
256 buddy->monitor = subscribe;
257 pjsua_pres_refresh();
258
259 PJSUA_UNLOCK();
260
261 return PJ_SUCCESS;
262}
263
264
265/*
266 * Dump presence subscriptions to log file.
267 */
268PJ_DEF(void) pjsua_pres_dump(pj_bool_t verbose)
269{
270 unsigned acc_id;
271 unsigned i;
272
273
274 PJSUA_LOCK();
275
276 /*
277 * When no detail is required, just dump number of server and client
278 * subscriptions.
279 */
280 if (verbose == PJ_FALSE) {
281
282 int count = 0;
283
284 for (acc_id=0; acc_id<PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) {
285
286 if (!pjsua_var.acc[acc_id].valid)
287 continue;
288
289 if (!pj_list_empty(&pjsua_var.acc[acc_id].pres_srv_list)) {
290 struct pjsua_srv_pres *uapres;
291
292 uapres = pjsua_var.acc[acc_id].pres_srv_list.next;
293 while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) {
294 ++count;
295 uapres = uapres->next;
296 }
297 }
298 }
299
300 PJ_LOG(3,(THIS_FILE, "Number of server/UAS subscriptions: %d",
301 count));
302
303 count = 0;
304
305 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
306 if (pjsua_var.buddy[i].uri.slen == 0)
307 continue;
308 if (pjsua_var.buddy[i].sub) {
309 ++count;
310 }
311 }
312
313 PJ_LOG(3,(THIS_FILE, "Number of client/UAC subscriptions: %d",
314 count));
315 PJSUA_UNLOCK();
316 return;
317 }
318
319
320 /*
321 * Dumping all server (UAS) subscriptions
322 */
323 PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:"));
324
325 for (acc_id=0; acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++acc_id) {
326
327 if (!pjsua_var.acc[acc_id].valid)
328 continue;
329
330 PJ_LOG(3,(THIS_FILE, " %.*s",
331 (int)pjsua_var.acc[acc_id].cfg.id.slen,
332 pjsua_var.acc[acc_id].cfg.id.ptr));
333
334 if (pj_list_empty(&pjsua_var.acc[acc_id].pres_srv_list)) {
335
336 PJ_LOG(3,(THIS_FILE, " - none - "));
337
338 } else {
339 struct pjsua_srv_pres *uapres;
340
341 uapres = pjsua_var.acc[acc_id].pres_srv_list.next;
342 while (uapres != &pjsua_var.acc[acc_id].pres_srv_list) {
343
344 PJ_LOG(3,(THIS_FILE, " %10s %s",
345 pjsip_evsub_get_state_name(uapres->sub),
346 uapres->remote));
347
348 uapres = uapres->next;
349 }
350 }
351 }
352
353 /*
354 * Dumping all client (UAC) subscriptions
355 */
356 PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:"));
357
358 if (pjsua_var.buddy_cnt == 0) {
359
360 PJ_LOG(3,(THIS_FILE, " - no buddy list - "));
361
362 } else {
363 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
364
365 if (pjsua_var.buddy[i].uri.slen == 0)
366 continue;
367
368 if (pjsua_var.buddy[i].sub) {
369 PJ_LOG(3,(THIS_FILE, " %10s %.*s",
370 pjsip_evsub_get_state_name(pjsua_var.buddy[i].sub),
371 (int)pjsua_var.buddy[i].uri.slen,
372 pjsua_var.buddy[i].uri.ptr));
373 } else {
374 PJ_LOG(3,(THIS_FILE, " %10s %.*s",
375 "(null)",
376 (int)pjsua_var.buddy[i].uri.slen,
377 pjsua_var.buddy[i].uri.ptr));
378 }
379 }
380 }
381
382 PJSUA_UNLOCK();
383}
384
385
386/***************************************************************************
387 * Server subscription.
Benny Prijono834aee32006-02-19 01:38:06 +0000388 */
389
390/* Proto */
391static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata);
392
393/* The module instance. */
394static pjsip_module mod_pjsua_pres =
395{
396 NULL, NULL, /* prev, next. */
397 { "mod-pjsua-pres", 14 }, /* Name. */
398 -1, /* Id */
399 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
Benny Prijono834aee32006-02-19 01:38:06 +0000400 NULL, /* load() */
401 NULL, /* start() */
402 NULL, /* stop() */
403 NULL, /* unload() */
404 &pres_on_rx_request, /* on_rx_request() */
405 NULL, /* on_rx_response() */
406 NULL, /* on_tx_request. */
407 NULL, /* on_tx_response() */
408 NULL, /* on_tsx_state() */
409
410};
411
412
413/* Callback called when *server* subscription state has changed. */
414static void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event)
415{
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000416 pjsua_srv_pres *uapres;
Benny Prijono834aee32006-02-19 01:38:06 +0000417
418 PJ_UNUSED_ARG(event);
419
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000420 PJSUA_LOCK();
421
422 uapres = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
Benny Prijono834aee32006-02-19 01:38:06 +0000423 if (uapres) {
424 PJ_LOG(3,(THIS_FILE, "Server subscription to %s is %s",
425 uapres->remote, pjsip_evsub_get_state_name(sub)));
426
427 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000428 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
Benny Prijono834aee32006-02-19 01:38:06 +0000429 pj_list_erase(uapres);
430 }
431 }
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000432
433 PJSUA_UNLOCK();
Benny Prijono834aee32006-02-19 01:38:06 +0000434}
435
436/* This is called when request is received.
437 * We need to check for incoming SUBSCRIBE request.
438 */
439static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata)
440{
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000441 int acc_id;
Benny Prijono6f979412006-06-15 12:25:46 +0000442 pjsua_acc *acc;
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000443 pj_str_t contact;
Benny Prijono834aee32006-02-19 01:38:06 +0000444 pjsip_method *req_method = &rdata->msg_info.msg->line.req.method;
445 pjsua_srv_pres *uapres;
446 pjsip_evsub *sub;
447 pjsip_evsub_user pres_cb;
448 pjsip_tx_data *tdata;
449 pjsip_pres_status pres_status;
450 pjsip_dialog *dlg;
451 pj_status_t status;
452
453 if (pjsip_method_cmp(req_method, &pjsip_subscribe_method) != 0)
454 return PJ_FALSE;
455
456 /* Incoming SUBSCRIBE: */
457
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000458 PJSUA_LOCK();
459
Benny Prijonoa91a0032006-02-26 21:23:45 +0000460 /* Find which account for the incoming request. */
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000461 acc_id = pjsua_acc_find_for_incoming(rdata);
Benny Prijono6f979412006-06-15 12:25:46 +0000462 acc = &pjsua_var.acc[acc_id];
Benny Prijonoa91a0032006-02-26 21:23:45 +0000463
Benny Prijono6f979412006-06-15 12:25:46 +0000464 PJ_LOG(4,(THIS_FILE, "Creating server subscription, using account %d",
465 acc_id));
466
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000467 /* Create suitable Contact header */
468 status = pjsua_acc_create_uas_contact(rdata->tp_info.pool, &contact,
469 acc_id, rdata);
470 if (status != PJ_SUCCESS) {
471 pjsua_perror(THIS_FILE, "Unable to generate Contact header", status);
472 PJSUA_UNLOCK();
473 return PJ_TRUE;
474 }
475
Benny Prijono834aee32006-02-19 01:38:06 +0000476 /* Create UAS dialog: */
Benny Prijonodc39fe82006-05-26 12:17:46 +0000477 status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata,
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000478 &contact, &dlg);
Benny Prijono834aee32006-02-19 01:38:06 +0000479 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000480 pjsua_perror(THIS_FILE,
481 "Unable to create UAS dialog for subscription",
482 status);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000483 PJSUA_UNLOCK();
484 return PJ_TRUE;
Benny Prijono834aee32006-02-19 01:38:06 +0000485 }
486
Benny Prijono6f979412006-06-15 12:25:46 +0000487 /* Set credentials. */
488 pjsip_auth_clt_set_credentials(&dlg->auth_sess, acc->cred_cnt, acc->cred);
489
Benny Prijono834aee32006-02-19 01:38:06 +0000490 /* Init callback: */
Benny Prijonoac623b32006-07-03 15:19:31 +0000491 pj_bzero(&pres_cb, sizeof(pres_cb));
Benny Prijono834aee32006-02-19 01:38:06 +0000492 pres_cb.on_evsub_state = &pres_evsub_on_srv_state;
493
494 /* Create server presence subscription: */
495 status = pjsip_pres_create_uas( dlg, &pres_cb, rdata, &sub);
496 if (status != PJ_SUCCESS) {
Benny Prijono1c2bf462006-03-05 11:54:02 +0000497 pjsip_dlg_terminate(dlg);
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000498 pjsua_perror(THIS_FILE, "Unable to create server subscription",
499 status);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000500 PJSUA_UNLOCK();
501 return PJ_TRUE;
Benny Prijono834aee32006-02-19 01:38:06 +0000502 }
503
504 /* Attach our data to the subscription: */
505 uapres = pj_pool_alloc(dlg->pool, sizeof(pjsua_srv_pres));
506 uapres->sub = sub;
507 uapres->remote = pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE);
508 status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri,
509 uapres->remote, PJSIP_MAX_URL_SIZE);
510 if (status < 1)
511 pj_ansi_strcpy(uapres->remote, "<-- url is too long-->");
512 else
513 uapres->remote[status] = '\0';
514
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000515 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, uapres);
Benny Prijono834aee32006-02-19 01:38:06 +0000516
517 /* Add server subscription to the list: */
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000518 pj_list_push_back(&pjsua_var.acc[acc_id].pres_srv_list, uapres);
Benny Prijono834aee32006-02-19 01:38:06 +0000519
520
521 /* Create and send 200 (OK) to the SUBSCRIBE request: */
522 status = pjsip_pres_accept(sub, rdata, 200, NULL);
523 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000524 pjsua_perror(THIS_FILE, "Unable to accept presence subscription",
525 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000526 pj_list_erase(uapres);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000527 pjsip_pres_terminate(sub, PJ_FALSE);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000528 PJSUA_UNLOCK();
Benny Prijono834aee32006-02-19 01:38:06 +0000529 return PJ_FALSE;
530 }
531
532
533 /* Set our online status: */
Benny Prijonoac623b32006-07-03 15:19:31 +0000534 pj_bzero(&pres_status, sizeof(pres_status));
Benny Prijono834aee32006-02-19 01:38:06 +0000535 pres_status.info_cnt = 1;
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000536 pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status;
537 //Both pjsua_var.local_uri and pjsua_var.contact_uri are enclosed in "<" and ">"
Benny Prijono834aee32006-02-19 01:38:06 +0000538 //causing XML parsing to fail.
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000539 //pres_status.info[0].contact = pjsua_var.local_uri;
Benny Prijono834aee32006-02-19 01:38:06 +0000540
541 pjsip_pres_set_status(sub, &pres_status);
542
543 /* Create and send the first NOTIFY to active subscription: */
544 status = pjsip_pres_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, NULL,
545 NULL, &tdata);
Benny Prijono21b9ad92006-08-15 13:11:22 +0000546 if (status == PJ_SUCCESS) {
547 pjsua_process_msg_data(tdata, NULL);
Benny Prijono834aee32006-02-19 01:38:06 +0000548 status = pjsip_pres_send_request( sub, tdata);
Benny Prijono21b9ad92006-08-15 13:11:22 +0000549 }
Benny Prijono834aee32006-02-19 01:38:06 +0000550
551 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000552 pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY",
553 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000554 pj_list_erase(uapres);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000555 pjsip_pres_terminate(sub, PJ_FALSE);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000556 PJSUA_UNLOCK();
Benny Prijono834aee32006-02-19 01:38:06 +0000557 return PJ_FALSE;
558 }
559
560
561 /* Done: */
562
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000563 PJSUA_UNLOCK();
564
Benny Prijono834aee32006-02-19 01:38:06 +0000565 return PJ_TRUE;
566}
567
568
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000569/*
570 * Client presence publication callback.
571 */
572static void publish_cb(struct pjsip_publishc_cbparam *param)
573{
574 pjsua_acc *acc = param->token;
575
576 if (param->code/100 != 2 || param->status != PJ_SUCCESS) {
577 if (param->status != PJ_SUCCESS) {
578 char errmsg[PJ_ERR_MSG_SIZE];
579
580 pj_strerror(param->status, errmsg, sizeof(errmsg));
581 PJ_LOG(1,(THIS_FILE,
582 "Client publication (PUBLISH) failed, status=%d, msg=%s",
583 param->status, errmsg));
584 } else {
585 PJ_LOG(1,(THIS_FILE,
586 "Client publication (PUBLISH) failed (%d/%.*s)",
587 param->code, (int)param->reason.slen,
588 param->reason.ptr));
589 }
590
591 pjsip_publishc_destroy(param->pubc);
592 acc->publish_sess = NULL;
593 }
594}
595
596
597/*
598 * Send PUBLISH request.
599 */
600static pj_status_t send_publish(int acc_id, pj_bool_t active)
601{
602 pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg;
603 pjsua_acc *acc = &pjsua_var.acc[acc_id];
604 pjsip_pres_status pres_status;
605 pjsip_tx_data *tdata;
606 pj_status_t status;
607
608
609 /* Create PUBLISH request */
610 if (active) {
611 status = pjsip_publishc_publish(acc->publish_sess, PJ_TRUE, &tdata);
612 if (status != PJ_SUCCESS) {
613 pjsua_perror(THIS_FILE, "Error creating PUBLISH request", status);
614 goto on_error;
615 }
616
617 /* Set our online status: */
618 pj_bzero(&pres_status, sizeof(pres_status));
619 pres_status.info_cnt = 1;
620 pres_status.info[0].basic_open = acc->online_status;
621
622 /* Create and add PIDF message body */
623 status = pjsip_pres_create_pidf(tdata->pool, &pres_status,
624 &acc_cfg->id, &tdata->msg->body);
625 if (status != PJ_SUCCESS) {
626 pjsua_perror(THIS_FILE, "Error creating PIDF for PUBLISH request",
627 status);
628 pjsip_tx_data_dec_ref(tdata);
629 goto on_error;
630 }
631 } else {
632 status = pjsip_publishc_unpublish(acc->publish_sess, &tdata);
633 if (status != PJ_SUCCESS) {
634 pjsua_perror(THIS_FILE, "Error creating PUBLISH request", status);
635 goto on_error;
636 }
637 }
638
639 /* Add headers etc */
640 pjsua_process_msg_data(tdata, NULL);
641
642 /* Send the PUBLISH request */
643 status = pjsip_publishc_send(acc->publish_sess, tdata);
644 if (status != PJ_SUCCESS) {
645 pjsua_perror(THIS_FILE, "Error sending PUBLISH request", status);
646 goto on_error;
647 }
648
649 acc->publish_state = acc->online_status;
650 return PJ_SUCCESS;
651
652on_error:
653 pjsip_publishc_destroy(acc->publish_sess);
654 acc->publish_sess = NULL;
655 return status;
656}
657
658
659/* Create client publish session */
660static pj_status_t create_publish(int acc_id)
661{
662 const pj_str_t STR_PRESENCE = { "presence", 8 };
663 pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg;
664 pjsua_acc *acc = &pjsua_var.acc[acc_id];
665 pj_status_t status;
666
667 /* Create and init client publication session */
668 if (acc_cfg->publish_enabled) {
669
670 /* Create client publication */
671 status = pjsip_publishc_create(pjsua_var.endpt, 0, acc, &publish_cb,
672 &acc->publish_sess);
673 if (status != PJ_SUCCESS) {
674 acc->publish_sess = NULL;
675 return status;
676 }
677
678 /* Initialize client publication */
679 status = pjsip_publishc_init(acc->publish_sess, &STR_PRESENCE,
680 &acc_cfg->id, &acc_cfg->id,
681 &acc_cfg->id,
682 PJSUA_PUBLISH_EXPIRATION);
683 if (status != PJ_SUCCESS) {
684 acc->publish_sess = NULL;
685 return status;
686 }
687
688 /* Send initial PUBLISH request */
689 if (acc->online_status != 0) {
690 status = send_publish(acc_id, PJ_TRUE);
691 if (status != PJ_SUCCESS)
692 return status;
693 }
694
695 } else {
696 acc->publish_sess = NULL;
697 }
698
699 return PJ_SUCCESS;
700}
701
702
703/* Init presence for account */
704pj_status_t pjsua_pres_init_acc(int acc_id)
705{
706 pjsua_acc *acc = &pjsua_var.acc[acc_id];
707
708 /* Init presence subscription */
709 pj_list_init(&acc->pres_srv_list);
710
711
712 return create_publish(acc_id);
713}
714
715
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000716/* Terminate server subscription for the account */
717void pjsua_pres_delete_acc(int acc_id)
Benny Prijono834aee32006-02-19 01:38:06 +0000718{
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000719 pjsua_acc *acc = &pjsua_var.acc[acc_id];
720 pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg;
Benny Prijono834aee32006-02-19 01:38:06 +0000721 pjsua_srv_pres *uapres;
722
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000723 uapres = pjsua_var.acc[acc_id].pres_srv_list.next;
Benny Prijono834aee32006-02-19 01:38:06 +0000724
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000725 while (uapres != &acc->pres_srv_list) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000726
727 pjsip_pres_status pres_status;
728 pj_str_t reason = { "noresource", 10 };
729 pjsip_tx_data *tdata;
730
731 pjsip_pres_get_status(uapres->sub, &pres_status);
732
733 pres_status.info[0].basic_open = pjsua_var.acc[acc_id].online_status;
734 pjsip_pres_set_status(uapres->sub, &pres_status);
735
736 if (pjsip_pres_notify(uapres->sub,
737 PJSIP_EVSUB_STATE_TERMINATED, NULL,
738 &reason, &tdata)==PJ_SUCCESS)
739 {
740 pjsip_pres_send_request(uapres->sub, tdata);
741 }
742
743 uapres = uapres->next;
744 }
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000745
746 if (acc->publish_sess) {
747 acc->online_status = PJ_FALSE;
748 send_publish(acc_id, PJ_FALSE);
749 if (acc->publish_sess) {
750 pjsip_publishc_destroy(acc->publish_sess);
751 acc->publish_sess = NULL;
752 }
753 acc_cfg->publish_enabled = PJ_FALSE;
754 }
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000755}
756
757
758/* Refresh subscription (e.g. when our online status has changed) */
759static void refresh_server_subscription(int acc_id)
760{
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000761 pjsua_acc *acc = &pjsua_var.acc[acc_id];
762 pjsua_acc_config *acc_cfg = &pjsua_var.acc[acc_id].cfg;
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000763 pjsua_srv_pres *uapres;
764
765 uapres = pjsua_var.acc[acc_id].pres_srv_list.next;
766
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000767 while (uapres != &acc->pres_srv_list) {
Benny Prijono834aee32006-02-19 01:38:06 +0000768
769 pjsip_pres_status pres_status;
770 pjsip_tx_data *tdata;
771
772 pjsip_pres_get_status(uapres->sub, &pres_status);
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000773 if (pres_status.info[0].basic_open != acc->online_status) {
774 pres_status.info[0].basic_open = acc->online_status;
Benny Prijono834aee32006-02-19 01:38:06 +0000775 pjsip_pres_set_status(uapres->sub, &pres_status);
776
Benny Prijono21b9ad92006-08-15 13:11:22 +0000777 if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS) {
778 pjsua_process_msg_data(tdata, NULL);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000779 pjsip_pres_send_request(uapres->sub, tdata);
Benny Prijono21b9ad92006-08-15 13:11:22 +0000780 }
Benny Prijono834aee32006-02-19 01:38:06 +0000781 }
782
783 uapres = uapres->next;
784 }
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000785
786 /* Send PUBLISH if required */
787 if (acc_cfg->publish_enabled) {
788 if (acc->publish_sess == NULL)
789 create_publish(acc_id);
790
791 if (acc->publish_sess && acc->publish_state != acc->online_status) {
792 send_publish(acc_id, PJ_TRUE);
793 }
794 }
Benny Prijono834aee32006-02-19 01:38:06 +0000795}
796
797
798
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000799/***************************************************************************
800 * Client subscription.
Benny Prijono834aee32006-02-19 01:38:06 +0000801 */
802
803/* Callback called when *client* subscription state has changed. */
804static void pjsua_evsub_on_state( pjsip_evsub *sub, pjsip_event *event)
805{
806 pjsua_buddy *buddy;
807
808 PJ_UNUSED_ARG(event);
809
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000810 PJSUA_LOCK();
811
812 buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
Benny Prijono834aee32006-02-19 01:38:06 +0000813 if (buddy) {
814 PJ_LOG(3,(THIS_FILE,
Benny Prijono9fc735d2006-05-28 14:58:12 +0000815 "Presence subscription to %.*s is %s",
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000816 (int)pjsua_var.buddy[buddy->index].uri.slen,
817 pjsua_var.buddy[buddy->index].uri.ptr,
Benny Prijono834aee32006-02-19 01:38:06 +0000818 pjsip_evsub_get_state_name(sub)));
819
820 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
821 buddy->sub = NULL;
822 buddy->status.info_cnt = 0;
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000823 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL);
Benny Prijono834aee32006-02-19 01:38:06 +0000824 }
Benny Prijono9fc735d2006-05-28 14:58:12 +0000825
826 /* Call callback */
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000827 if (pjsua_var.ua_cfg.cb.on_buddy_state)
828 (*pjsua_var.ua_cfg.cb.on_buddy_state)(buddy->index);
Benny Prijono834aee32006-02-19 01:38:06 +0000829 }
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000830
831 PJSUA_UNLOCK();
Benny Prijono834aee32006-02-19 01:38:06 +0000832}
833
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000834
835/* Callback when transaction state has changed. */
836static void pjsua_evsub_on_tsx_state(pjsip_evsub *sub,
837 pjsip_transaction *tsx,
838 pjsip_event *event)
839{
840 pjsua_buddy *buddy;
841 pjsip_contact_hdr *contact_hdr;
842
843 PJSUA_LOCK();
844
845 buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
846 if (!buddy) {
847 PJSUA_UNLOCK();
848 return;
849 }
850
851 /* We only use this to update buddy's Contact, when it's not
852 * set.
853 */
854 if (buddy->contact.slen != 0) {
855 /* Contact already set */
856 PJSUA_UNLOCK();
857 return;
858 }
859
860 /* Only care about 2xx response to outgoing SUBSCRIBE */
861 if (tsx->status_code/100 != 2 ||
862 tsx->role != PJSIP_UAC_ROLE ||
863 event->type != PJSIP_EVENT_RX_MSG ||
864 pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method)!=0)
865 {
866 PJSUA_UNLOCK();
867 return;
868 }
869
870 /* Find contact header. */
871 contact_hdr = pjsip_msg_find_hdr(event->body.rx_msg.rdata->msg_info.msg,
872 PJSIP_H_CONTACT, NULL);
873 if (!contact_hdr) {
874 PJSUA_UNLOCK();
875 return;
876 }
877
878 buddy->contact.ptr = pj_pool_alloc(pjsua_var.pool, PJSIP_MAX_URL_SIZE);
879 buddy->contact.slen = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR,
880 contact_hdr->uri,
881 buddy->contact.ptr,
882 PJSIP_MAX_URL_SIZE);
883 if (buddy->contact.slen < 0)
884 buddy->contact.slen = 0;
885
886 PJSUA_UNLOCK();
887}
888
889
Benny Prijono834aee32006-02-19 01:38:06 +0000890/* Callback called when we receive NOTIFY */
891static void pjsua_evsub_on_rx_notify(pjsip_evsub *sub,
892 pjsip_rx_data *rdata,
893 int *p_st_code,
894 pj_str_t **p_st_text,
895 pjsip_hdr *res_hdr,
896 pjsip_msg_body **p_body)
897{
898 pjsua_buddy *buddy;
899
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000900 PJSUA_LOCK();
901
902 buddy = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id);
Benny Prijono834aee32006-02-19 01:38:06 +0000903 if (buddy) {
904 /* Update our info. */
905 pjsip_pres_get_status(sub, &buddy->status);
Benny Prijono834aee32006-02-19 01:38:06 +0000906 }
907
908 /* The default is to send 200 response to NOTIFY.
909 * Just leave it there..
910 */
911 PJ_UNUSED_ARG(rdata);
912 PJ_UNUSED_ARG(p_st_code);
913 PJ_UNUSED_ARG(p_st_text);
914 PJ_UNUSED_ARG(res_hdr);
915 PJ_UNUSED_ARG(p_body);
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000916
917 PJSUA_UNLOCK();
Benny Prijono834aee32006-02-19 01:38:06 +0000918}
919
920
921/* Event subscription callback. */
922static pjsip_evsub_user pres_callback =
923{
924 &pjsua_evsub_on_state,
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000925 &pjsua_evsub_on_tsx_state,
Benny Prijono834aee32006-02-19 01:38:06 +0000926
927 NULL, /* on_rx_refresh: don't care about SUBSCRIBE refresh, unless
928 * we want to authenticate
929 */
930
931 &pjsua_evsub_on_rx_notify,
932
933 NULL, /* on_client_refresh: Use default behaviour, which is to
934 * refresh client subscription. */
935
936 NULL, /* on_server_timeout: Use default behaviour, which is to send
937 * NOTIFY to terminate.
938 */
939};
940
941
942/* It does what it says.. */
943static void subscribe_buddy_presence(unsigned index)
944{
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000945 pjsua_buddy *buddy;
946 int acc_id;
947 pjsua_acc *acc;
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000948 pj_str_t contact;
Benny Prijono834aee32006-02-19 01:38:06 +0000949 pjsip_dialog *dlg;
950 pjsip_tx_data *tdata;
951 pj_status_t status;
952
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000953 buddy = &pjsua_var.buddy[index];
954 acc_id = pjsua_acc_find_for_outgoing(&buddy->uri);
Benny Prijono8b1889b2006-06-06 18:40:40 +0000955
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000956 acc = &pjsua_var.acc[acc_id];
Benny Prijonoa91a0032006-02-26 21:23:45 +0000957
Benny Prijonob4a17c92006-07-10 14:40:21 +0000958 PJ_LOG(4,(THIS_FILE, "Using account %d for buddy %d subscription",
959 acc_id, index));
960
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000961 /* Generate suitable Contact header */
962 status = pjsua_acc_create_uac_contact(pjsua_var.pool, &contact,
963 acc_id, &buddy->uri);
964 if (status != PJ_SUCCESS) {
965 pjsua_perror(THIS_FILE, "Unable to generate Contact header", status);
966 return;
967 }
968
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000969 /* Create UAC dialog */
Benny Prijono834aee32006-02-19 01:38:06 +0000970 status = pjsip_dlg_create_uac( pjsip_ua_instance(),
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000971 &acc->cfg.id,
Benny Prijonoc570f2d2006-07-18 00:33:02 +0000972 &contact,
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000973 &buddy->uri,
Benny Prijono834aee32006-02-19 01:38:06 +0000974 NULL, &dlg);
975 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000976 pjsua_perror(THIS_FILE, "Unable to create dialog",
977 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000978 return;
979 }
980
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000981 /* Set route-set */
982 if (!pj_list_empty(&acc->route_set)) {
983 pjsip_dlg_set_route_set(dlg, &acc->route_set);
984 }
985
986 /* Set credentials */
987 if (acc->cred_cnt) {
Benny Prijonodc39fe82006-05-26 12:17:46 +0000988 pjsip_auth_clt_set_credentials( &dlg->auth_sess,
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000989 acc->cred_cnt, acc->cred);
Benny Prijonodc39fe82006-05-26 12:17:46 +0000990 }
Benny Prijono1d8d6082006-04-29 12:38:25 +0000991
Benny Prijono834aee32006-02-19 01:38:06 +0000992 status = pjsip_pres_create_uac( dlg, &pres_callback,
Benny Prijono3a5e1ab2006-08-15 20:26:34 +0000993 PJSIP_EVSUB_NO_EVENT_ID, &buddy->sub);
Benny Prijono834aee32006-02-19 01:38:06 +0000994 if (status != PJ_SUCCESS) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +0000995 pjsua_var.buddy[index].sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000996 pjsua_perror(THIS_FILE, "Unable to create presence client",
997 status);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000998 pjsip_dlg_terminate(dlg);
Benny Prijono834aee32006-02-19 01:38:06 +0000999 return;
1000 }
1001
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001002 pjsip_evsub_set_mod_data(buddy->sub, pjsua_var.mod.id, buddy);
Benny Prijono834aee32006-02-19 01:38:06 +00001003
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001004 status = pjsip_pres_initiate(buddy->sub, -1, &tdata);
Benny Prijono834aee32006-02-19 01:38:06 +00001005 if (status != PJ_SUCCESS) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001006 pjsip_pres_terminate(buddy->sub, PJ_FALSE);
1007 buddy->sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +00001008 pjsua_perror(THIS_FILE, "Unable to create initial SUBSCRIBE",
1009 status);
Benny Prijono834aee32006-02-19 01:38:06 +00001010 return;
1011 }
1012
Benny Prijono21b9ad92006-08-15 13:11:22 +00001013 pjsua_process_msg_data(tdata, NULL);
1014
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001015 status = pjsip_pres_send_request(buddy->sub, tdata);
Benny Prijono834aee32006-02-19 01:38:06 +00001016 if (status != PJ_SUCCESS) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001017 pjsip_pres_terminate(buddy->sub, PJ_FALSE);
1018 buddy->sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +00001019 pjsua_perror(THIS_FILE, "Unable to send initial SUBSCRIBE",
1020 status);
Benny Prijono834aee32006-02-19 01:38:06 +00001021 return;
1022 }
Benny Prijono834aee32006-02-19 01:38:06 +00001023}
1024
1025
1026/* It does what it says... */
1027static void unsubscribe_buddy_presence(unsigned index)
1028{
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001029 pjsua_buddy *buddy;
Benny Prijono834aee32006-02-19 01:38:06 +00001030 pjsip_tx_data *tdata;
1031 pj_status_t status;
1032
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001033 buddy = &pjsua_var.buddy[index];
1034
1035 if (buddy->sub == NULL)
Benny Prijono834aee32006-02-19 01:38:06 +00001036 return;
1037
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001038 if (pjsip_evsub_get_state(buddy->sub) == PJSIP_EVSUB_STATE_TERMINATED) {
1039 pjsua_var.buddy[index].sub = NULL;
Benny Prijono834aee32006-02-19 01:38:06 +00001040 return;
1041 }
1042
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001043 status = pjsip_pres_initiate( buddy->sub, 0, &tdata);
Benny Prijono21b9ad92006-08-15 13:11:22 +00001044 if (status == PJ_SUCCESS) {
1045 pjsua_process_msg_data(tdata, NULL);
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001046 status = pjsip_pres_send_request( buddy->sub, tdata );
Benny Prijono21b9ad92006-08-15 13:11:22 +00001047 }
Benny Prijono834aee32006-02-19 01:38:06 +00001048
Benny Prijono1c2bf462006-03-05 11:54:02 +00001049 if (status != PJ_SUCCESS) {
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001050 pjsip_pres_terminate(buddy->sub, PJ_FALSE);
1051 buddy->sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +00001052 pjsua_perror(THIS_FILE, "Unable to unsubscribe presence",
1053 status);
Benny Prijono834aee32006-02-19 01:38:06 +00001054 }
1055}
1056
1057
1058/* It does what it says.. */
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001059static void refresh_client_subscriptions(void)
Benny Prijono834aee32006-02-19 01:38:06 +00001060{
Benny Prijono9fc735d2006-05-28 14:58:12 +00001061 unsigned i;
Benny Prijono834aee32006-02-19 01:38:06 +00001062
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001063 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
Benny Prijono834aee32006-02-19 01:38:06 +00001064
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001065 if (!pjsua_var.buddy[i].uri.slen)
1066 continue;
1067
1068 if (pjsua_var.buddy[i].monitor && !pjsua_var.buddy[i].sub) {
Benny Prijono834aee32006-02-19 01:38:06 +00001069 subscribe_buddy_presence(i);
1070
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001071 } else if (!pjsua_var.buddy[i].monitor && pjsua_var.buddy[i].sub) {
Benny Prijono834aee32006-02-19 01:38:06 +00001072 unsubscribe_buddy_presence(i);
1073
1074 }
1075 }
1076}
1077
1078
1079/*
1080 * Init presence
1081 */
1082pj_status_t pjsua_pres_init()
1083{
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001084 unsigned i;
Benny Prijono834aee32006-02-19 01:38:06 +00001085 pj_status_t status;
1086
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001087 status = pjsip_endpt_register_module( pjsua_var.endpt, &mod_pjsua_pres);
Benny Prijono834aee32006-02-19 01:38:06 +00001088 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +00001089 pjsua_perror(THIS_FILE, "Unable to register pjsua presence module",
1090 status);
Benny Prijono834aee32006-02-19 01:38:06 +00001091 }
1092
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001093 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
1094 reset_buddy(i);
1095 }
1096
Benny Prijono834aee32006-02-19 01:38:06 +00001097 return status;
1098}
1099
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001100
Benny Prijono834aee32006-02-19 01:38:06 +00001101/*
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001102 * Start presence subsystem.
Benny Prijono9fc735d2006-05-28 14:58:12 +00001103 */
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001104pj_status_t pjsua_pres_start(void)
Benny Prijono9fc735d2006-05-28 14:58:12 +00001105{
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001106 /* Nothing to do (is it?) */
Benny Prijono9fc735d2006-05-28 14:58:12 +00001107 return PJ_SUCCESS;
1108}
1109
1110
1111/*
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001112 * Refresh presence subscriptions
Benny Prijono834aee32006-02-19 01:38:06 +00001113 */
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001114void pjsua_pres_refresh()
Benny Prijono834aee32006-02-19 01:38:06 +00001115{
Benny Prijonob9b32ab2006-06-01 12:28:44 +00001116 unsigned i;
1117
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001118 refresh_client_subscriptions();
Benny Prijonob9b32ab2006-06-01 12:28:44 +00001119
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001120 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1121 if (pjsua_var.acc[i].valid)
1122 refresh_server_subscription(i);
1123 }
Benny Prijono834aee32006-02-19 01:38:06 +00001124}
1125
1126
1127/*
1128 * Shutdown presence.
1129 */
1130void pjsua_pres_shutdown(void)
1131{
Benny Prijono9fc735d2006-05-28 14:58:12 +00001132 unsigned i;
Benny Prijono834aee32006-02-19 01:38:06 +00001133
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001134 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1135 if (!pjsua_var.acc[i].valid)
1136 continue;
1137 pjsua_pres_delete_acc(i);
Benny Prijonoa91a0032006-02-26 21:23:45 +00001138 }
1139
Benny Prijonoeebe9af2006-06-13 22:57:13 +00001140 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
1141 pjsua_var.buddy[i].monitor = 0;
Benny Prijono834aee32006-02-19 01:38:06 +00001142 }
Benny Prijonoa91a0032006-02-26 21:23:45 +00001143
Benny Prijonob9b32ab2006-06-01 12:28:44 +00001144 pjsua_pres_refresh();
Benny Prijono834aee32006-02-19 01:38:06 +00001145}