blob: f0774d5fa22a6c7cdbf9c1a8dcdcafc6d6246be9 [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 Prijono834aee32006-02-19 01:38:06 +000020
21/*
22 * pjsua_pres.c
23 *
24 * Presence related stuffs.
25 */
26
27#define THIS_FILE "pjsua_pres.c"
28
29
30
31/* **************************************************************************
32 * THE FOLLOWING PART HANDLES SERVER SUBSCRIPTION
33 * **************************************************************************
34 */
35
36/* Proto */
37static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata);
38
39/* The module instance. */
40static pjsip_module mod_pjsua_pres =
41{
42 NULL, NULL, /* prev, next. */
43 { "mod-pjsua-pres", 14 }, /* Name. */
44 -1, /* Id */
45 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
Benny Prijono834aee32006-02-19 01:38:06 +000046 NULL, /* load() */
47 NULL, /* start() */
48 NULL, /* stop() */
49 NULL, /* unload() */
50 &pres_on_rx_request, /* on_rx_request() */
51 NULL, /* on_rx_response() */
52 NULL, /* on_tx_request. */
53 NULL, /* on_tx_response() */
54 NULL, /* on_tsx_state() */
55
56};
57
58
59/* Callback called when *server* subscription state has changed. */
60static void pres_evsub_on_srv_state( pjsip_evsub *sub, pjsip_event *event)
61{
62 pjsua_srv_pres *uapres = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
63
64 PJ_UNUSED_ARG(event);
65
66 if (uapres) {
67 PJ_LOG(3,(THIS_FILE, "Server subscription to %s is %s",
68 uapres->remote, pjsip_evsub_get_state_name(sub)));
69
70 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
71 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL);
72 pj_list_erase(uapres);
73 }
74 }
75}
76
77/* This is called when request is received.
78 * We need to check for incoming SUBSCRIBE request.
79 */
80static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata)
81{
Benny Prijonoa91a0032006-02-26 21:23:45 +000082 int acc_index;
Benny Prijono834aee32006-02-19 01:38:06 +000083 pjsip_method *req_method = &rdata->msg_info.msg->line.req.method;
84 pjsua_srv_pres *uapres;
85 pjsip_evsub *sub;
86 pjsip_evsub_user pres_cb;
87 pjsip_tx_data *tdata;
88 pjsip_pres_status pres_status;
89 pjsip_dialog *dlg;
90 pj_status_t status;
91
92 if (pjsip_method_cmp(req_method, &pjsip_subscribe_method) != 0)
93 return PJ_FALSE;
94
95 /* Incoming SUBSCRIBE: */
96
Benny Prijonoa91a0032006-02-26 21:23:45 +000097 /* Find which account for the incoming request. */
98 acc_index = pjsua_find_account_for_incoming(rdata);
99
Benny Prijono834aee32006-02-19 01:38:06 +0000100 /* Create UAS dialog: */
101 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
Benny Prijonoa91a0032006-02-26 21:23:45 +0000102 &pjsua.acc[acc_index].contact_uri,
103 &dlg);
Benny Prijono834aee32006-02-19 01:38:06 +0000104 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000105 pjsua_perror(THIS_FILE,
106 "Unable to create UAS dialog for subscription",
107 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000108 return PJ_FALSE;
109 }
110
111 /* Init callback: */
112 pj_memset(&pres_cb, 0, sizeof(pres_cb));
113 pres_cb.on_evsub_state = &pres_evsub_on_srv_state;
114
115 /* Create server presence subscription: */
116 status = pjsip_pres_create_uas( dlg, &pres_cb, rdata, &sub);
117 if (status != PJ_SUCCESS) {
Benny Prijono1c2bf462006-03-05 11:54:02 +0000118 pjsip_dlg_terminate(dlg);
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000119 pjsua_perror(THIS_FILE, "Unable to create server subscription",
120 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000121 return PJ_FALSE;
122 }
123
124 /* Attach our data to the subscription: */
125 uapres = pj_pool_alloc(dlg->pool, sizeof(pjsua_srv_pres));
126 uapres->sub = sub;
127 uapres->remote = pj_pool_alloc(dlg->pool, PJSIP_MAX_URL_SIZE);
128 status = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->remote.info->uri,
129 uapres->remote, PJSIP_MAX_URL_SIZE);
130 if (status < 1)
131 pj_ansi_strcpy(uapres->remote, "<-- url is too long-->");
132 else
133 uapres->remote[status] = '\0';
134
135 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, uapres);
136
137 /* Add server subscription to the list: */
Benny Prijonoa91a0032006-02-26 21:23:45 +0000138 pj_list_push_back(&pjsua.acc[acc_index].pres_srv_list, uapres);
Benny Prijono834aee32006-02-19 01:38:06 +0000139
140
141 /* Create and send 200 (OK) to the SUBSCRIBE request: */
142 status = pjsip_pres_accept(sub, rdata, 200, NULL);
143 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000144 pjsua_perror(THIS_FILE, "Unable to accept presence subscription",
145 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000146 pj_list_erase(uapres);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000147 pjsip_pres_terminate(sub, PJ_FALSE);
Benny Prijono834aee32006-02-19 01:38:06 +0000148 return PJ_FALSE;
149 }
150
151
152 /* Set our online status: */
153 pj_memset(&pres_status, 0, sizeof(pres_status));
154 pres_status.info_cnt = 1;
Benny Prijonoa91a0032006-02-26 21:23:45 +0000155 pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status;
Benny Prijono834aee32006-02-19 01:38:06 +0000156 //Both pjsua.local_uri and pjsua.contact_uri are enclosed in "<" and ">"
157 //causing XML parsing to fail.
158 //pres_status.info[0].contact = pjsua.local_uri;
159
160 pjsip_pres_set_status(sub, &pres_status);
161
162 /* Create and send the first NOTIFY to active subscription: */
163 status = pjsip_pres_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, NULL,
164 NULL, &tdata);
165 if (status == PJ_SUCCESS)
166 status = pjsip_pres_send_request( sub, tdata);
167
168 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000169 pjsua_perror(THIS_FILE, "Unable to create/send NOTIFY",
170 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000171 pj_list_erase(uapres);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000172 pjsip_pres_terminate(sub, PJ_FALSE);
Benny Prijono834aee32006-02-19 01:38:06 +0000173 return PJ_FALSE;
174 }
175
176
177 /* Done: */
178
179 return PJ_TRUE;
180}
181
182
183/* Refresh subscription (e.g. when our online status has changed) */
Benny Prijonoa91a0032006-02-26 21:23:45 +0000184static void refresh_server_subscription(int acc_index)
Benny Prijono834aee32006-02-19 01:38:06 +0000185{
186 pjsua_srv_pres *uapres;
187
Benny Prijonoa91a0032006-02-26 21:23:45 +0000188 uapres = pjsua.acc[acc_index].pres_srv_list.next;
Benny Prijono834aee32006-02-19 01:38:06 +0000189
Benny Prijonoa91a0032006-02-26 21:23:45 +0000190 while (uapres != &pjsua.acc[acc_index].pres_srv_list) {
Benny Prijono834aee32006-02-19 01:38:06 +0000191
192 pjsip_pres_status pres_status;
193 pjsip_tx_data *tdata;
194
195 pjsip_pres_get_status(uapres->sub, &pres_status);
Benny Prijonoa91a0032006-02-26 21:23:45 +0000196 if (pres_status.info[0].basic_open != pjsua.acc[acc_index].online_status) {
197 pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status;
Benny Prijono834aee32006-02-19 01:38:06 +0000198 pjsip_pres_set_status(uapres->sub, &pres_status);
199
200 if (pjsua.quit_flag) {
201 pj_str_t reason = { "noresource", 10 };
202 if (pjsip_pres_notify(uapres->sub,
203 PJSIP_EVSUB_STATE_TERMINATED, NULL,
204 &reason, &tdata)==PJ_SUCCESS)
205 {
206 pjsip_pres_send_request(uapres->sub, tdata);
207 }
208 } else {
209 if (pjsip_pres_current_notify(uapres->sub, &tdata)==PJ_SUCCESS)
210 pjsip_pres_send_request(uapres->sub, tdata);
211 }
212 }
213
214 uapres = uapres->next;
215 }
216}
217
218
219
220/* **************************************************************************
221 * THE FOLLOWING PART HANDLES CLIENT SUBSCRIPTION
222 * **************************************************************************
223 */
224
225/* Callback called when *client* subscription state has changed. */
226static void pjsua_evsub_on_state( pjsip_evsub *sub, pjsip_event *event)
227{
228 pjsua_buddy *buddy;
229
230 PJ_UNUSED_ARG(event);
231
232 buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
233 if (buddy) {
234 PJ_LOG(3,(THIS_FILE,
235 "Presence subscription to %s is %s",
236 buddy->uri.ptr,
237 pjsip_evsub_get_state_name(sub)));
238
239 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
240 buddy->sub = NULL;
241 buddy->status.info_cnt = 0;
242 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL);
243 }
244 }
245}
246
247/* Callback called when we receive NOTIFY */
248static void pjsua_evsub_on_rx_notify(pjsip_evsub *sub,
249 pjsip_rx_data *rdata,
250 int *p_st_code,
251 pj_str_t **p_st_text,
252 pjsip_hdr *res_hdr,
253 pjsip_msg_body **p_body)
254{
255 pjsua_buddy *buddy;
256
257 buddy = pjsip_evsub_get_mod_data(sub, pjsua.mod.id);
258 if (buddy) {
259 /* Update our info. */
260 pjsip_pres_get_status(sub, &buddy->status);
261
262 if (buddy->status.info_cnt) {
263 PJ_LOG(3,(THIS_FILE, "%s is %s",
264 buddy->uri.ptr,
265 (buddy->status.info[0].basic_open?"online":"offline")));
266 } else {
267 PJ_LOG(3,(THIS_FILE, "No presence info for %s",
268 buddy->uri.ptr));
269 }
270 }
271
272 /* The default is to send 200 response to NOTIFY.
273 * Just leave it there..
274 */
275 PJ_UNUSED_ARG(rdata);
276 PJ_UNUSED_ARG(p_st_code);
277 PJ_UNUSED_ARG(p_st_text);
278 PJ_UNUSED_ARG(res_hdr);
279 PJ_UNUSED_ARG(p_body);
280}
281
282
283/* Event subscription callback. */
284static pjsip_evsub_user pres_callback =
285{
286 &pjsua_evsub_on_state,
287
288 NULL, /* on_tsx_state: don't care about transaction state. */
289
290 NULL, /* on_rx_refresh: don't care about SUBSCRIBE refresh, unless
291 * we want to authenticate
292 */
293
294 &pjsua_evsub_on_rx_notify,
295
296 NULL, /* on_client_refresh: Use default behaviour, which is to
297 * refresh client subscription. */
298
299 NULL, /* on_server_timeout: Use default behaviour, which is to send
300 * NOTIFY to terminate.
301 */
302};
303
304
305/* It does what it says.. */
306static void subscribe_buddy_presence(unsigned index)
307{
Benny Prijonoa91a0032006-02-26 21:23:45 +0000308 int acc_index;
Benny Prijono834aee32006-02-19 01:38:06 +0000309 pjsip_dialog *dlg;
310 pjsip_tx_data *tdata;
311 pj_status_t status;
312
Benny Prijonoa91a0032006-02-26 21:23:45 +0000313 acc_index = pjsua.buddies[index].acc_index;
314
Benny Prijono834aee32006-02-19 01:38:06 +0000315 status = pjsip_dlg_create_uac( pjsip_ua_instance(),
Benny Prijonoa91a0032006-02-26 21:23:45 +0000316 &pjsua.acc[acc_index].local_uri,
317 &pjsua.acc[acc_index].contact_uri,
Benny Prijono834aee32006-02-19 01:38:06 +0000318 &pjsua.buddies[index].uri,
319 NULL, &dlg);
320 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000321 pjsua_perror(THIS_FILE, "Unable to create dialog",
322 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000323 return;
324 }
325
326 status = pjsip_pres_create_uac( dlg, &pres_callback,
327 &pjsua.buddies[index].sub);
328 if (status != PJ_SUCCESS) {
329 pjsua.buddies[index].sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000330 pjsua_perror(THIS_FILE, "Unable to create presence client",
331 status);
Benny Prijono1c2bf462006-03-05 11:54:02 +0000332 pjsip_dlg_terminate(dlg);
Benny Prijono834aee32006-02-19 01:38:06 +0000333 return;
334 }
335
336 pjsip_evsub_set_mod_data(pjsua.buddies[index].sub, pjsua.mod.id,
337 &pjsua.buddies[index]);
338
Benny Prijonoa91a0032006-02-26 21:23:45 +0000339 status = pjsip_pres_initiate(pjsua.buddies[index].sub, -1, &tdata);
Benny Prijono834aee32006-02-19 01:38:06 +0000340 if (status != PJ_SUCCESS) {
Benny Prijono1c2bf462006-03-05 11:54:02 +0000341 pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE);
Benny Prijono834aee32006-02-19 01:38:06 +0000342 pjsua.buddies[index].sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000343 pjsua_perror(THIS_FILE, "Unable to create initial SUBSCRIBE",
344 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000345 return;
346 }
347
348 status = pjsip_pres_send_request(pjsua.buddies[index].sub, tdata);
349 if (status != PJ_SUCCESS) {
Benny Prijono1c2bf462006-03-05 11:54:02 +0000350 pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE);
Benny Prijono834aee32006-02-19 01:38:06 +0000351 pjsua.buddies[index].sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000352 pjsua_perror(THIS_FILE, "Unable to send initial SUBSCRIBE",
353 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000354 return;
355 }
Benny Prijono834aee32006-02-19 01:38:06 +0000356}
357
358
359/* It does what it says... */
360static void unsubscribe_buddy_presence(unsigned index)
361{
362 pjsip_tx_data *tdata;
363 pj_status_t status;
364
365 if (pjsua.buddies[index].sub == NULL)
366 return;
367
368 if (pjsip_evsub_get_state(pjsua.buddies[index].sub) ==
369 PJSIP_EVSUB_STATE_TERMINATED)
370 {
371 pjsua.buddies[index].sub = NULL;
372 return;
373 }
374
375 status = pjsip_pres_initiate( pjsua.buddies[index].sub, 0, &tdata);
376 if (status == PJ_SUCCESS)
377 status = pjsip_pres_send_request( pjsua.buddies[index].sub, tdata );
378
Benny Prijono1c2bf462006-03-05 11:54:02 +0000379 if (status != PJ_SUCCESS) {
Benny Prijono834aee32006-02-19 01:38:06 +0000380
Benny Prijono1c2bf462006-03-05 11:54:02 +0000381 pjsip_pres_terminate(pjsua.buddies[index].sub, PJ_FALSE);
382 pjsua.buddies[index].sub = NULL;
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000383 pjsua_perror(THIS_FILE, "Unable to unsubscribe presence",
384 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000385 }
386}
387
388
389/* It does what it says.. */
390static void refresh_client_subscription(void)
391{
Benny Prijonoa91a0032006-02-26 21:23:45 +0000392 int i;
Benny Prijono834aee32006-02-19 01:38:06 +0000393
394 for (i=0; i<pjsua.buddy_cnt; ++i) {
395
396 if (pjsua.buddies[i].monitor && !pjsua.buddies[i].sub) {
397 subscribe_buddy_presence(i);
398
399 } else if (!pjsua.buddies[i].monitor && pjsua.buddies[i].sub) {
400 unsubscribe_buddy_presence(i);
401
402 }
403 }
404}
405
406
407/*
408 * Init presence
409 */
410pj_status_t pjsua_pres_init()
411{
412 pj_status_t status;
413
414 status = pjsip_endpt_register_module( pjsua.endpt, &mod_pjsua_pres);
415 if (status != PJ_SUCCESS) {
Benny Prijonobcaed6c2006-02-19 15:37:19 +0000416 pjsua_perror(THIS_FILE, "Unable to register pjsua presence module",
417 status);
Benny Prijono834aee32006-02-19 01:38:06 +0000418 }
419
420 return status;
421}
422
423/*
424 * Refresh presence
425 */
Benny Prijonoa91a0032006-02-26 21:23:45 +0000426void pjsua_pres_refresh(int acc_index)
Benny Prijono834aee32006-02-19 01:38:06 +0000427{
428 refresh_client_subscription();
Benny Prijonoa91a0032006-02-26 21:23:45 +0000429 refresh_server_subscription(acc_index);
Benny Prijono834aee32006-02-19 01:38:06 +0000430}
431
432
433/*
434 * Shutdown presence.
435 */
436void pjsua_pres_shutdown(void)
437{
Benny Prijonoa91a0032006-02-26 21:23:45 +0000438 int acc_index;
439 int i;
Benny Prijono834aee32006-02-19 01:38:06 +0000440
Benny Prijonoa91a0032006-02-26 21:23:45 +0000441 for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) {
442 pjsua.acc[acc_index].online_status = 0;
443 }
444
Benny Prijono834aee32006-02-19 01:38:06 +0000445 for (i=0; i<pjsua.buddy_cnt; ++i) {
446 pjsua.buddies[i].monitor = 0;
447 }
Benny Prijonoa91a0032006-02-26 21:23:45 +0000448
449 for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) {
450 pjsua_pres_refresh(acc_index);
451 }
Benny Prijono834aee32006-02-19 01:38:06 +0000452}
453
454/*
455 * Dump presence status.
456 */
Benny Prijono1a174142006-03-01 20:46:13 +0000457void pjsua_pres_dump(pj_bool_t detail)
Benny Prijono834aee32006-02-19 01:38:06 +0000458{
Benny Prijonoa91a0032006-02-26 21:23:45 +0000459 int acc_index;
460 int i;
Benny Prijono834aee32006-02-19 01:38:06 +0000461
Benny Prijono1a174142006-03-01 20:46:13 +0000462
463 /*
464 * When no detail is required, just dump number of server and client
465 * subscriptions.
466 */
467 if (detail == PJ_FALSE) {
468
469 int count = 0;
470
471 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
472
473 if (!pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) {
474 struct pjsua_srv_pres *uapres;
475
476 uapres = pjsua.acc[acc_index].pres_srv_list.next;
477 while (uapres != &pjsua.acc[acc_index].pres_srv_list) {
478 ++count;
479 uapres = uapres->next;
480 }
481 }
482 }
483
484 PJ_LOG(3,(THIS_FILE, "Number of server/UAS subscriptions: %d",
485 count));
486
487 count = 0;
488
489 for (i=0; i<pjsua.buddy_cnt; ++i) {
490 if (pjsua.buddies[i].sub) {
491 ++count;
492 }
493 }
494
495 PJ_LOG(3,(THIS_FILE, "Number of client/UAC subscriptions: %d",
496 count));
497 return;
498 }
499
500
501 /*
502 * Dumping all server (UAS) subscriptions
503 */
Benny Prijono834aee32006-02-19 01:38:06 +0000504 PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:"));
Benny Prijono1a174142006-03-01 20:46:13 +0000505
Benny Prijonoa91a0032006-02-26 21:23:45 +0000506 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) {
Benny Prijono834aee32006-02-19 01:38:06 +0000507
Benny Prijonoa91a0032006-02-26 21:23:45 +0000508 PJ_LOG(3,(THIS_FILE, " %.*s",
509 (int)pjsua.acc[acc_index].local_uri.slen,
510 pjsua.acc[acc_index].local_uri.ptr));
Benny Prijono834aee32006-02-19 01:38:06 +0000511
Benny Prijonoa91a0032006-02-26 21:23:45 +0000512 if (pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) {
Benny Prijono1a174142006-03-01 20:46:13 +0000513
Benny Prijonoa91a0032006-02-26 21:23:45 +0000514 PJ_LOG(3,(THIS_FILE, " - none - "));
Benny Prijono1a174142006-03-01 20:46:13 +0000515
Benny Prijonoa91a0032006-02-26 21:23:45 +0000516 } else {
517 struct pjsua_srv_pres *uapres;
518
519 uapres = pjsua.acc[acc_index].pres_srv_list.next;
520 while (uapres != &pjsua.acc[acc_index].pres_srv_list) {
521
522 PJ_LOG(3,(THIS_FILE, " %10s %s",
523 pjsip_evsub_get_state_name(uapres->sub),
524 uapres->remote));
525
526 uapres = uapres->next;
527 }
Benny Prijono834aee32006-02-19 01:38:06 +0000528 }
529 }
530
Benny Prijono1a174142006-03-01 20:46:13 +0000531 /*
532 * Dumping all client (UAC) subscriptions
533 */
Benny Prijono834aee32006-02-19 01:38:06 +0000534 PJ_LOG(3,(THIS_FILE, "Dumping pjsua client subscriptions:"));
Benny Prijono1a174142006-03-01 20:46:13 +0000535
Benny Prijono834aee32006-02-19 01:38:06 +0000536 if (pjsua.buddy_cnt == 0) {
Benny Prijono1a174142006-03-01 20:46:13 +0000537
Benny Prijono834aee32006-02-19 01:38:06 +0000538 PJ_LOG(3,(THIS_FILE, " - no buddy list - "));
Benny Prijono1a174142006-03-01 20:46:13 +0000539
Benny Prijono834aee32006-02-19 01:38:06 +0000540 } else {
541 for (i=0; i<pjsua.buddy_cnt; ++i) {
542
543 if (pjsua.buddies[i].sub) {
544 PJ_LOG(3,(THIS_FILE, " %10s %s",
545 pjsip_evsub_get_state_name(pjsua.buddies[i].sub),
546 pjsua.buddies[i].uri.ptr));
547 } else {
548 PJ_LOG(3,(THIS_FILE, " %10s %s",
549 "(null)",
550 pjsua.buddies[i].uri.ptr));
551 }
552 }
553 }
554}
555