~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/pjsip-simple/mwi.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: mwi.c 4172 2012-06-19 14:35:18Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pjsip-simple/mwi.h>
 
21
#include <pjsip-simple/errno.h>
 
22
#include <pjsip-simple/evsub_msg.h>
 
23
#include <pjsip/sip_module.h>
 
24
#include <pjsip/sip_endpoint.h>
 
25
#include <pjsip/sip_dialog.h>
 
26
#include <pj/assert.h>
 
27
#include <pj/guid.h>
 
28
#include <pj/log.h>
 
29
#include <pj/os.h>
 
30
#include <pj/pool.h>
 
31
#include <pj/string.h>
 
32
 
 
33
 
 
34
#define THIS_FILE                   "mwi.c"
 
35
 
 
36
 /*
 
37
 * MWI module (mod-mdi)
 
38
 */
 
39
static struct pjsip_module mod_mwi = 
 
40
{
 
41
    NULL, NULL,                     /* prev, next.                      */
 
42
    { "mod-mwi", 7 },               /* Name.                            */
 
43
    -1,                             /* Id                               */
 
44
    PJSIP_MOD_PRIORITY_DIALOG_USAGE,/* Priority                         */
 
45
    NULL,                           /* load()                           */
 
46
    NULL,                           /* start()                          */
 
47
    NULL,                           /* stop()                           */
 
48
    NULL,                           /* unload()                         */
 
49
    NULL,                           /* on_rx_request()                  */
 
50
    NULL,                           /* on_rx_response()                 */
 
51
    NULL,                           /* on_tx_request.                   */
 
52
    NULL,                           /* on_tx_response()                 */
 
53
    NULL,                           /* on_tsx_state()                   */
 
54
};
 
55
 
 
56
 
 
57
/*
 
58
 * This structure describe an mwi agent (both client and server)
 
59
 */
 
60
typedef struct pjsip_mwi
 
61
{
 
62
    pjsip_evsub         *sub;           /**< Event subscribtion record.     */
 
63
    pjsip_dialog        *dlg;           /**< The dialog.                    */
 
64
    pjsip_evsub_user     user_cb;       /**< The user callback.             */
 
65
 
 
66
    /* These are for server subscriptions */
 
67
    pj_pool_t           *body_pool;     /**< Pool to save message body      */
 
68
    pjsip_media_type     mime_type;     /**< MIME type of last msg body     */
 
69
    pj_str_t             body;          /**< Last sent message body         */
 
70
} pjsip_mwi;
 
71
 
 
72
 
 
73
/*
 
74
 * Forward decl for evsub callbacks.
 
75
 */
 
76
static void mwi_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
 
77
static void mwi_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
 
78
                                    pjsip_event *event);
 
79
static void mwi_on_evsub_rx_refresh( pjsip_evsub *sub, 
 
80
                                     pjsip_rx_data *rdata,
 
81
                                     int *p_st_code,
 
82
                                     pj_str_t **p_st_text,
 
83
                                     pjsip_hdr *res_hdr,
 
84
                                     pjsip_msg_body **p_body);
 
85
static void mwi_on_evsub_rx_notify( pjsip_evsub *sub, 
 
86
                                    pjsip_rx_data *rdata,
 
87
                                    int *p_st_code,
 
88
                                    pj_str_t **p_st_text,
 
89
                                    pjsip_hdr *res_hdr,
 
90
                                    pjsip_msg_body **p_body);
 
91
static void mwi_on_evsub_client_refresh(pjsip_evsub *sub);
 
92
static void mwi_on_evsub_server_timeout(pjsip_evsub *sub);
 
93
 
 
94
 
 
95
/*
 
96
 * Event subscription callback for mwi.
 
97
 */
 
98
static pjsip_evsub_user mwi_user = 
 
99
{
 
100
    &mwi_on_evsub_state,
 
101
    &mwi_on_evsub_tsx_state,
 
102
    &mwi_on_evsub_rx_refresh,
 
103
    &mwi_on_evsub_rx_notify,
 
104
    &mwi_on_evsub_client_refresh,
 
105
    &mwi_on_evsub_server_timeout,
 
106
};
 
107
 
 
108
 
 
109
/*
 
110
 * Some static constants.
 
111
 */
 
112
static const pj_str_t STR_EVENT          = { "Event", 5 };
 
113
static const pj_str_t STR_MWI            = { "message-summary", 15 };
 
114
static const pj_str_t STR_APP_SIMPLE_SMS = { "application/simple-message-summary", 34};
 
115
 
 
116
/*
 
117
 * Init mwi module.
 
118
 */
 
119
PJ_DEF(pj_status_t) pjsip_mwi_init_module( pjsip_endpoint *endpt,
 
120
                                           pjsip_module *mod_evsub)
 
121
{
 
122
    pj_status_t status;
 
123
    pj_str_t accept[1];
 
124
 
 
125
    /* Check arguments. */
 
126
    PJ_ASSERT_RETURN(endpt && mod_evsub, PJ_EINVAL);
 
127
 
 
128
    /* Must have not been registered */
 
129
    PJ_ASSERT_RETURN(mod_mwi.id == -1, PJ_EINVALIDOP);
 
130
 
 
131
    /* Register to endpoint */
 
132
    status = pjsip_endpt_register_module(endpt, &mod_mwi);
 
133
    if (status != PJ_SUCCESS)
 
134
        return status;
 
135
 
 
136
    accept[0] = STR_APP_SIMPLE_SMS;
 
137
 
 
138
    /* Register event package to event module. */
 
139
    status = pjsip_evsub_register_pkg( &mod_mwi, &STR_MWI, 
 
140
                                       PJSIP_MWI_DEFAULT_EXPIRES, 
 
141
                                       PJ_ARRAY_SIZE(accept), accept);
 
142
    if (status != PJ_SUCCESS) {
 
143
        pjsip_endpt_unregister_module(endpt, &mod_mwi);
 
144
        return status;
 
145
    }
 
146
 
 
147
    return PJ_SUCCESS;
 
148
}
 
149
 
 
150
 
 
151
/*
 
152
 * Get mwi module instance.
 
153
 */
 
154
PJ_DEF(pjsip_module*) pjsip_mwi_instance(void)
 
155
{
 
156
    return &mod_mwi;
 
157
}
 
158
 
 
159
 
 
160
/*
 
161
 * Create client subscription.
 
162
 */
 
163
PJ_DEF(pj_status_t) pjsip_mwi_create_uac( pjsip_dialog *dlg,
 
164
                                          const pjsip_evsub_user *user_cb,
 
165
                                          unsigned options,
 
166
                                          pjsip_evsub **p_evsub )
 
167
{
 
168
    pj_status_t status;
 
169
    pjsip_mwi *mwi;
 
170
    pjsip_evsub *sub;
 
171
 
 
172
    PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);
 
173
 
 
174
    PJ_UNUSED_ARG(options);
 
175
 
 
176
    pjsip_dlg_inc_lock(dlg);
 
177
 
 
178
    /* Create event subscription */
 
179
    status = pjsip_evsub_create_uac( dlg,  &mwi_user, &STR_MWI, 
 
180
                                     options, &sub);
 
181
    if (status != PJ_SUCCESS)
 
182
        goto on_return;
 
183
 
 
184
    /* Create mwi */
 
185
    mwi = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_mwi);
 
186
    mwi->dlg = dlg;
 
187
    mwi->sub = sub;
 
188
    if (user_cb)
 
189
        pj_memcpy(&mwi->user_cb, user_cb, sizeof(pjsip_evsub_user));
 
190
 
 
191
    /* Attach to evsub */
 
192
    pjsip_evsub_set_mod_data(sub, mod_mwi.id, mwi);
 
193
 
 
194
    *p_evsub = sub;
 
195
 
 
196
on_return:
 
197
    pjsip_dlg_dec_lock(dlg);
 
198
    return status;
 
199
}
 
200
 
 
201
 
 
202
/*
 
203
 * Create server subscription.
 
204
 */
 
205
PJ_DEF(pj_status_t) pjsip_mwi_create_uas( pjsip_dialog *dlg,
 
206
                                          const pjsip_evsub_user *user_cb,
 
207
                                          pjsip_rx_data *rdata,
 
208
                                          pjsip_evsub **p_evsub )
 
209
{
 
210
    pjsip_accept_hdr *accept;
 
211
    pjsip_event_hdr *event;
 
212
    pjsip_evsub *sub;
 
213
    pjsip_mwi *mwi;
 
214
    char obj_name[PJ_MAX_OBJ_NAME];
 
215
    pj_status_t status;
 
216
 
 
217
    /* Check arguments */
 
218
    PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);
 
219
 
 
220
    /* Must be request message */
 
221
    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
 
222
                     PJSIP_ENOTREQUESTMSG);
 
223
 
 
224
    /* Check that request is SUBSCRIBE */
 
225
    PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
 
226
                                      &pjsip_subscribe_method)==0,
 
227
                     PJSIP_SIMPLE_ENOTSUBSCRIBE);
 
228
 
 
229
    /* Check that Event header contains "mwi" */
 
230
    event = (pjsip_event_hdr*)
 
231
            pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_EVENT, NULL);
 
232
    if (!event) {
 
233
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);
 
234
    }
 
235
    if (pj_stricmp(&event->event_type, &STR_MWI) != 0) {
 
236
        return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EVENT);
 
237
    }
 
238
 
 
239
    /* Check that request contains compatible Accept header. */
 
240
    accept = (pjsip_accept_hdr*)
 
241
             pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
 
242
    if (accept) {
 
243
        unsigned i;
 
244
        for (i=0; i<accept->count; ++i) {
 
245
            if (pj_stricmp(&accept->values[i], &STR_APP_SIMPLE_SMS)==0) {
 
246
                break;
 
247
            }
 
248
        }
 
249
 
 
250
        if (i==accept->count) {
 
251
            /* Nothing is acceptable */
 
252
            return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);
 
253
        }
 
254
 
 
255
    } else {
 
256
        /* No Accept header. 
 
257
         * Assume client supports "application/simple-message-summary" 
 
258
        */
 
259
    }
 
260
 
 
261
    /* Lock dialog */
 
262
    pjsip_dlg_inc_lock(dlg);
 
263
 
 
264
 
 
265
    /* Create server subscription */
 
266
    status = pjsip_evsub_create_uas( dlg, &mwi_user, rdata, 0, &sub);
 
267
    if (status != PJ_SUCCESS)
 
268
        goto on_return;
 
269
 
 
270
    /* Create server mwi subscription */
 
271
    mwi = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_mwi);
 
272
    mwi->dlg = dlg;
 
273
    mwi->sub = sub;
 
274
    if (user_cb)
 
275
        pj_memcpy(&mwi->user_cb, user_cb, sizeof(pjsip_evsub_user));
 
276
 
 
277
    pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "mwibd%p", dlg->pool);
 
278
    mwi->body_pool = pj_pool_create(dlg->pool->factory, obj_name, 
 
279
                                    512, 512, NULL);
 
280
 
 
281
    /* Attach to evsub */
 
282
    pjsip_evsub_set_mod_data(sub, mod_mwi.id, mwi);
 
283
 
 
284
    /* Done: */
 
285
    *p_evsub = sub;
 
286
 
 
287
on_return:
 
288
    pjsip_dlg_dec_lock(dlg);
 
289
    return status;
 
290
}
 
291
 
 
292
 
 
293
/*
 
294
 * Forcefully terminate mwi.
 
295
 */
 
296
PJ_DEF(pj_status_t) pjsip_mwi_terminate( pjsip_evsub *sub,
 
297
                                         pj_bool_t notify )
 
298
{
 
299
    return pjsip_evsub_terminate(sub, notify);
 
300
}
 
301
 
 
302
/*
 
303
 * Create SUBSCRIBE
 
304
 */
 
305
PJ_DEF(pj_status_t) pjsip_mwi_initiate( pjsip_evsub *sub,
 
306
                                        pj_int32_t expires,
 
307
                                        pjsip_tx_data **p_tdata)
 
308
{
 
309
    return pjsip_evsub_initiate(sub, &pjsip_subscribe_method, expires, 
 
310
                                p_tdata);
 
311
}
 
312
 
 
313
 
 
314
/*
 
315
 * Accept incoming subscription.
 
316
 */
 
317
PJ_DEF(pj_status_t) pjsip_mwi_accept( pjsip_evsub *sub,
 
318
                                      pjsip_rx_data *rdata,
 
319
                                      int st_code,
 
320
                                      const pjsip_hdr *hdr_list )
 
321
{
 
322
    return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
 
323
}
 
324
 
 
325
/*
 
326
 * Create message body and attach it to the (NOTIFY) request.
 
327
 */
 
328
static pj_status_t mwi_create_msg_body( pjsip_mwi *mwi, 
 
329
                                        pjsip_tx_data *tdata)
 
330
{
 
331
    pjsip_msg_body *body;
 
332
    pj_str_t dup_text;
 
333
 
 
334
    PJ_ASSERT_RETURN(mwi->mime_type.type.slen && mwi->body.slen, PJ_EINVALIDOP);
 
335
    
 
336
    /* Clone the message body and mime type */
 
337
    pj_strdup(tdata->pool, &dup_text, &mwi->body);
 
338
 
 
339
    /* Create the message body */
 
340
    body = PJ_POOL_ZALLOC_T(tdata->pool, pjsip_msg_body);
 
341
    pjsip_media_type_cp(tdata->pool, &body->content_type, &mwi->mime_type);
 
342
    body->data = dup_text.ptr;
 
343
    body->len = (unsigned)dup_text.slen;
 
344
    body->print_body = &pjsip_print_text_body;
 
345
    body->clone_data = &pjsip_clone_text_data;
 
346
 
 
347
    /* Attach to tdata */
 
348
    tdata->msg->body = body;
 
349
 
 
350
    return PJ_SUCCESS;
 
351
}
 
352
 
 
353
 
 
354
/*
 
355
 * Create NOTIFY
 
356
 */
 
357
PJ_DEF(pj_status_t) pjsip_mwi_notify(  pjsip_evsub *sub,
 
358
                                       pjsip_evsub_state state,
 
359
                                       const pj_str_t *state_str,
 
360
                                       const pj_str_t *reason,
 
361
                                       const pjsip_media_type *mime_type,
 
362
                                       const pj_str_t *body,
 
363
                                       pjsip_tx_data **p_tdata)
 
364
{
 
365
    pjsip_mwi *mwi;
 
366
    pjsip_tx_data *tdata;
 
367
    pj_status_t status;
 
368
    
 
369
    /* Check arguments. */
 
370
    PJ_ASSERT_RETURN(sub && mime_type && body && p_tdata, PJ_EINVAL);
 
371
 
 
372
    /* Get the mwi object. */
 
373
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
374
    PJ_ASSERT_RETURN(mwi != NULL, PJ_EINVALIDOP);
 
375
 
 
376
    /* Lock object. */
 
377
    pjsip_dlg_inc_lock(mwi->dlg);
 
378
 
 
379
    /* Create the NOTIFY request. */
 
380
    status = pjsip_evsub_notify( sub, state, state_str, reason, &tdata);
 
381
    if (status != PJ_SUCCESS)
 
382
        goto on_return;
 
383
 
 
384
    /* Update the cached message body */
 
385
    if (mime_type || body)
 
386
        pj_pool_reset(mwi->body_pool);
 
387
    if (mime_type)
 
388
        pjsip_media_type_cp(mwi->body_pool, &mwi->mime_type, mime_type);
 
389
    if (body)
 
390
        pj_strdup(mwi->body_pool, &mwi->body, body);
 
391
 
 
392
    /* Create message body */
 
393
    status = mwi_create_msg_body( mwi, tdata );
 
394
    if (status != PJ_SUCCESS)
 
395
        goto on_return;
 
396
 
 
397
    /* Done. */
 
398
    *p_tdata = tdata;
 
399
 
 
400
on_return:
 
401
    pjsip_dlg_dec_lock(mwi->dlg);
 
402
    return status;
 
403
}
 
404
 
 
405
 
 
406
/*
 
407
 * Create NOTIFY that reflect current state.
 
408
 */
 
409
PJ_DEF(pj_status_t) pjsip_mwi_current_notify( pjsip_evsub *sub,
 
410
                                              pjsip_tx_data **p_tdata )
 
411
{
 
412
    pjsip_mwi *mwi;
 
413
    pjsip_tx_data *tdata;
 
414
    pj_status_t status;
 
415
    
 
416
    /* Check arguments. */
 
417
    PJ_ASSERT_RETURN(sub && p_tdata, PJ_EINVAL);
 
418
 
 
419
    /* Get the mwi object. */
 
420
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
421
    PJ_ASSERT_RETURN(mwi != NULL, PJ_EINVALIDOP);
 
422
 
 
423
    /* Lock object. */
 
424
    pjsip_dlg_inc_lock(mwi->dlg);
 
425
 
 
426
    /* Create the NOTIFY request. */
 
427
    status = pjsip_evsub_current_notify( sub, &tdata);
 
428
    if (status != PJ_SUCCESS)
 
429
        goto on_return;
 
430
 
 
431
 
 
432
    /* Create message body to reflect the mwi status. */
 
433
    status = mwi_create_msg_body( mwi, tdata );
 
434
    if (status != PJ_SUCCESS)
 
435
        goto on_return;
 
436
 
 
437
    /* Done. */
 
438
    *p_tdata = tdata;
 
439
 
 
440
on_return:
 
441
    pjsip_dlg_dec_lock(mwi->dlg);
 
442
    return status;
 
443
}
 
444
 
 
445
 
 
446
/*
 
447
 * Send request.
 
448
 */
 
449
PJ_DEF(pj_status_t) pjsip_mwi_send_request( pjsip_evsub *sub,
 
450
                                             pjsip_tx_data *tdata )
 
451
{
 
452
    return pjsip_evsub_send_request(sub, tdata);
 
453
}
 
454
 
 
455
/*
 
456
 * This callback is called by event subscription when subscription
 
457
 * state has changed.
 
458
 */
 
459
static void mwi_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
 
460
{
 
461
    pjsip_mwi *mwi;
 
462
 
 
463
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
464
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
465
 
 
466
    if (mwi->user_cb.on_evsub_state)
 
467
        (*mwi->user_cb.on_evsub_state)(sub, event);
 
468
 
 
469
    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
 
470
        if (mwi->body_pool) {
 
471
            pj_pool_release(mwi->body_pool);
 
472
            mwi->body_pool = NULL;
 
473
        }
 
474
    }
 
475
}
 
476
 
 
477
/*
 
478
 * Called when transaction state has changed.
 
479
 */
 
480
static void mwi_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,
 
481
                                     pjsip_event *event)
 
482
{
 
483
    pjsip_mwi *mwi;
 
484
 
 
485
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
486
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
487
 
 
488
    if (mwi->user_cb.on_tsx_state)
 
489
        (*mwi->user_cb.on_tsx_state)(sub, tsx, event);
 
490
}
 
491
 
 
492
 
 
493
/*
 
494
 * Called when SUBSCRIBE is received.
 
495
 */
 
496
static void mwi_on_evsub_rx_refresh( pjsip_evsub *sub, 
 
497
                                     pjsip_rx_data *rdata,
 
498
                                     int *p_st_code,
 
499
                                     pj_str_t **p_st_text,
 
500
                                     pjsip_hdr *res_hdr,
 
501
                                     pjsip_msg_body **p_body)
 
502
{
 
503
    pjsip_mwi *mwi;
 
504
 
 
505
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
506
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
507
 
 
508
    if (mwi->user_cb.on_rx_refresh) {
 
509
        (*mwi->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,
 
510
                                       res_hdr, p_body);
 
511
 
 
512
    } else {
 
513
        /* Implementors MUST send NOTIFY if it implements on_rx_refresh */
 
514
        pjsip_tx_data *tdata;
 
515
        pj_str_t timeout = { "timeout", 7};
 
516
        pj_status_t status;
 
517
 
 
518
        if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {
 
519
            status = pjsip_mwi_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,
 
520
                                       NULL, &timeout, NULL, NULL, &tdata);
 
521
        } else {
 
522
            status = pjsip_mwi_current_notify(sub, &tdata);
 
523
        }
 
524
 
 
525
        if (status == PJ_SUCCESS)
 
526
            pjsip_mwi_send_request(sub, tdata);
 
527
    }
 
528
}
 
529
 
 
530
 
 
531
/*
 
532
 * Called when NOTIFY is received.
 
533
 */
 
534
static void mwi_on_evsub_rx_notify( pjsip_evsub *sub, 
 
535
                                     pjsip_rx_data *rdata,
 
536
                                     int *p_st_code,
 
537
                                     pj_str_t **p_st_text,
 
538
                                     pjsip_hdr *res_hdr,
 
539
                                     pjsip_msg_body **p_body)
 
540
{
 
541
    pjsip_mwi *mwi;
 
542
 
 
543
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
544
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
545
 
 
546
    /* Just notify application. */
 
547
    if (mwi->user_cb.on_rx_notify) {
 
548
        (*mwi->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text, 
 
549
                                     res_hdr, p_body);
 
550
    }
 
551
}
 
552
 
 
553
/*
 
554
 * Called when it's time to send SUBSCRIBE.
 
555
 */
 
556
static void mwi_on_evsub_client_refresh(pjsip_evsub *sub)
 
557
{
 
558
    pjsip_mwi *mwi;
 
559
 
 
560
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
561
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
562
 
 
563
    if (mwi->user_cb.on_client_refresh) {
 
564
        (*mwi->user_cb.on_client_refresh)(sub);
 
565
    } else {
 
566
        pj_status_t status;
 
567
        pjsip_tx_data *tdata;
 
568
 
 
569
        status = pjsip_mwi_initiate(sub, -1, &tdata);
 
570
        if (status == PJ_SUCCESS)
 
571
            pjsip_mwi_send_request(sub, tdata);
 
572
    }
 
573
}
 
574
 
 
575
/*
 
576
 * Called when no refresh is received after the interval.
 
577
 */
 
578
static void mwi_on_evsub_server_timeout(pjsip_evsub *sub)
 
579
{
 
580
    pjsip_mwi *mwi;
 
581
 
 
582
    mwi = (pjsip_mwi*) pjsip_evsub_get_mod_data(sub, mod_mwi.id);
 
583
    PJ_ASSERT_ON_FAIL(mwi!=NULL, {return;});
 
584
 
 
585
    if (mwi->user_cb.on_server_timeout) {
 
586
        (*mwi->user_cb.on_server_timeout)(sub);
 
587
    } else {
 
588
        pj_status_t status;
 
589
        pjsip_tx_data *tdata;
 
590
        pj_str_t reason = { "timeout", 7 };
 
591
 
 
592
        status = pjsip_mwi_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,
 
593
                                   NULL, &reason, NULL, NULL, &tdata);
 
594
        if (status == PJ_SUCCESS)
 
595
            pjsip_mwi_send_request(sub, tdata);
 
596
    }
 
597
}
 
598