~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/pjsip-ua/sip_100rel.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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: sip_100rel.c 4208 2012-07-18 07:52:33Z ming $ */
 
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-ua/sip_100rel.h>
 
21
#include <pjsip/sip_endpoint.h>
 
22
#include <pjsip/sip_event.h>
 
23
#include <pjsip/sip_module.h>
 
24
#include <pjsip/sip_transaction.h>
 
25
#include <pj/assert.h>
 
26
#include <pj/ctype.h>
 
27
#include <pj/log.h>
 
28
#include <pj/os.h>
 
29
#include <pj/pool.h>
 
30
#include <pj/rand.h>
 
31
#include <pj/string.h>
 
32
 
 
33
#define THIS_FILE       "sip_100rel.c"
 
34
 
 
35
/* PRACK method */
 
36
PJ_DEF_DATA(const pjsip_method) pjsip_prack_method =
 
37
{
 
38
    PJSIP_OTHER_METHOD,
 
39
    { "PRACK", 5 }
 
40
};
 
41
 
 
42
typedef struct dlg_data dlg_data;
 
43
 
 
44
/*
 
45
 * Static prototypes.
 
46
 */
 
47
static pj_status_t mod_100rel_load(pjsip_endpoint *endpt);
 
48
 
 
49
static void on_retransmit(pj_timer_heap_t *timer_heap,
 
50
                          struct pj_timer_entry *entry);
 
51
 
 
52
 
 
53
const pj_str_t tag_100rel = { "100rel", 6 };
 
54
const pj_str_t RSEQ = { "RSeq", 4 };
 
55
const pj_str_t RACK = { "RAck", 4 };
 
56
 
 
57
 
 
58
/* 100rel module */
 
59
static struct mod_100rel
 
60
{
 
61
    pjsip_module         mod;
 
62
    pjsip_endpoint      *endpt;
 
63
} mod_100rel = 
 
64
{
 
65
    {
 
66
        NULL, NULL,                         /* prev, next.              */
 
67
        { "mod-100rel", 10 },               /* Name.                    */
 
68
        -1,                                 /* Id                       */
 
69
        PJSIP_MOD_PRIORITY_DIALOG_USAGE,    /* Priority                 */
 
70
        &mod_100rel_load,                   /* load()                   */
 
71
        NULL,                               /* start()                  */
 
72
        NULL,                               /* stop()                   */
 
73
        NULL,                               /* unload()                 */
 
74
        NULL,                               /* on_rx_request()          */
 
75
        NULL,                               /* on_rx_response()         */
 
76
        NULL,                               /* on_tx_request.           */
 
77
        NULL,                               /* on_tx_response()         */
 
78
        NULL,                               /* on_tsx_state()           */
 
79
    }
 
80
 
 
81
};
 
82
 
 
83
/* List of pending transmission (may include the final response as well) */
 
84
typedef struct tx_data_list_t
 
85
{
 
86
        PJ_DECL_LIST_MEMBER(struct tx_data_list_t);
 
87
        pj_uint32_t      rseq;
 
88
        pjsip_tx_data   *tdata;
 
89
} tx_data_list_t;
 
90
 
 
91
 
 
92
/* Below, UAS and UAC roles are of the INVITE transaction */
 
93
 
 
94
/* UAS state. */
 
95
typedef struct uas_state_t
 
96
{
 
97
        pj_int32_t       cseq;
 
98
        pj_uint32_t      rseq;  /* Initialized to -1 */
 
99
        tx_data_list_t   tx_data_list;
 
100
        unsigned         retransmit_count;
 
101
        pj_timer_entry   retransmit_timer;
 
102
} uas_state_t;
 
103
 
 
104
 
 
105
/* UAC state */
 
106
typedef struct uac_state_t
 
107
{
 
108
    pj_str_t            tag;    /* To tag               */
 
109
    pj_int32_t          cseq;
 
110
    pj_uint32_t         rseq;   /* Initialized to -1    */
 
111
    struct uac_state_t *next;   /* next call leg        */
 
112
} uac_state_t;
 
113
 
 
114
 
 
115
/* State attached to each dialog. */
 
116
struct dlg_data
 
117
{
 
118
        pjsip_inv_session       *inv;
 
119
        uas_state_t             *uas_state;
 
120
        uac_state_t             *uac_state_list;
 
121
};
 
122
 
 
123
 
 
124
/*****************************************************************************
 
125
 **
 
126
 ** Module
 
127
 **
 
128
 *****************************************************************************
 
129
 */
 
130
static pj_status_t mod_100rel_load(pjsip_endpoint *endpt)
 
131
{
 
132
    mod_100rel.endpt = endpt;
 
133
    pjsip_endpt_add_capability(endpt, &mod_100rel.mod, 
 
134
                               PJSIP_H_ALLOW, NULL,
 
135
                               1, &pjsip_prack_method.name);
 
136
    pjsip_endpt_add_capability(endpt, &mod_100rel.mod, 
 
137
                               PJSIP_H_SUPPORTED, NULL,
 
138
                               1, &tag_100rel);
 
139
 
 
140
    return PJ_SUCCESS;
 
141
}
 
142
 
 
143
static pjsip_require_hdr *find_req_hdr(pjsip_msg *msg)
 
144
{
 
145
    pjsip_require_hdr *hreq;
 
146
 
 
147
    hreq = (pjsip_require_hdr*)
 
148
            pjsip_msg_find_hdr(msg, PJSIP_H_REQUIRE, NULL);
 
149
 
 
150
    while (hreq) {
 
151
        unsigned i;
 
152
        for (i=0; i<hreq->count; ++i) {
 
153
            if (!pj_stricmp(&hreq->values[i], &tag_100rel)) {
 
154
                return hreq;
 
155
            }
 
156
        }
 
157
 
 
158
        if ((void*)hreq->next == (void*)&msg->hdr)
 
159
            return NULL;
 
160
 
 
161
        hreq = (pjsip_require_hdr*)
 
162
                pjsip_msg_find_hdr(msg, PJSIP_H_REQUIRE, hreq->next);
 
163
 
 
164
    }
 
165
 
 
166
    return NULL;
 
167
}
 
168
 
 
169
 
 
170
/*
 
171
 * Get PRACK method constant. 
 
172
 */
 
173
PJ_DEF(const pjsip_method*) pjsip_get_prack_method(void)
 
174
{
 
175
    return &pjsip_prack_method;
 
176
}
 
177
 
 
178
 
 
179
/*
 
180
 * init module
 
181
 */
 
182
PJ_DEF(pj_status_t) pjsip_100rel_init_module(pjsip_endpoint *endpt)
 
183
{
 
184
    if (mod_100rel.mod.id != -1)
 
185
        return PJ_SUCCESS;
 
186
 
 
187
    return pjsip_endpt_register_module(endpt, &mod_100rel.mod);
 
188
}
 
189
 
 
190
 
 
191
/*
 
192
 * API: attach 100rel support in invite session. Called by
 
193
 *      sip_inv.c
 
194
 */
 
195
PJ_DEF(pj_status_t) pjsip_100rel_attach(pjsip_inv_session *inv)
 
196
{
 
197
    dlg_data *dd;
 
198
 
 
199
    /* Check that 100rel module has been initialized */
 
200
    PJ_ASSERT_RETURN(mod_100rel.mod.id >= 0, PJ_EINVALIDOP);
 
201
 
 
202
    /* Create and attach as dialog usage */
 
203
    dd = PJ_POOL_ZALLOC_T(inv->dlg->pool, dlg_data);
 
204
    dd->inv = inv;
 
205
    pjsip_dlg_add_usage(inv->dlg, &mod_100rel.mod, (void*)dd);
 
206
 
 
207
    PJ_LOG(5,(dd->inv->dlg->obj_name, "100rel module attached"));
 
208
 
 
209
    return PJ_SUCCESS;
 
210
}
 
211
 
 
212
 
 
213
/*
 
214
 * Check if incoming response has reliable provisional response feature.
 
215
 */
 
216
PJ_DEF(pj_bool_t) pjsip_100rel_is_reliable(pjsip_rx_data *rdata)
 
217
{
 
218
    pjsip_msg *msg = rdata->msg_info.msg;
 
219
 
 
220
    PJ_ASSERT_RETURN(msg->type == PJSIP_RESPONSE_MSG, PJ_FALSE);
 
221
 
 
222
    return msg->line.status.code > 100 && msg->line.status.code < 200 &&
 
223
           rdata->msg_info.require != NULL &&
 
224
           find_req_hdr(msg) != NULL;
 
225
}
 
226
 
 
227
 
 
228
/*
 
229
 * Create PRACK request for the incoming reliable provisional response.
 
230
 */
 
231
PJ_DEF(pj_status_t) pjsip_100rel_create_prack( pjsip_inv_session *inv,
 
232
                                               pjsip_rx_data *rdata,
 
233
                                               pjsip_tx_data **p_tdata)
 
234
{
 
235
    dlg_data *dd;
 
236
    uac_state_t *uac_state = NULL;
 
237
    const pj_str_t *to_tag = &rdata->msg_info.to->tag;
 
238
    pjsip_transaction *tsx;
 
239
    pjsip_msg *msg;
 
240
    pjsip_generic_string_hdr *rseq_hdr;
 
241
    pjsip_generic_string_hdr *rack_hdr;
 
242
    unsigned rseq;
 
243
    pj_str_t rack;
 
244
    char rack_buf[80];
 
245
    pjsip_tx_data *tdata;
 
246
    pj_status_t status;
 
247
 
 
248
    *p_tdata = NULL;
 
249
 
 
250
    dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
 
251
    PJ_ASSERT_RETURN(dd != NULL, PJSIP_ENOTINITIALIZED);
 
252
 
 
253
    tsx = pjsip_rdata_get_tsx(rdata);
 
254
    msg = rdata->msg_info.msg;
 
255
 
 
256
    /* Check our assumptions */
 
257
    pj_assert( tsx->role == PJSIP_ROLE_UAC &&
 
258
               tsx->method.id == PJSIP_INVITE_METHOD &&
 
259
               msg->line.status.code > 100 &&
 
260
               msg->line.status.code < 200);
 
261
 
 
262
 
 
263
    /* Get the RSeq header */
 
264
    rseq_hdr = (pjsip_generic_string_hdr*)
 
265
               pjsip_msg_find_hdr_by_name(msg, &RSEQ, NULL);
 
266
    if (rseq_hdr == NULL) {
 
267
        PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
268
                 "Ignoring 100rel response with no RSeq header"));
 
269
        return PJSIP_EMISSINGHDR;
 
270
    }
 
271
    rseq = (pj_uint32_t) pj_strtoul(&rseq_hdr->hvalue);
 
272
 
 
273
    /* Find UAC state for the specified call leg */
 
274
    uac_state = dd->uac_state_list;
 
275
    while (uac_state) {
 
276
        if (pj_stricmp(&uac_state->tag, to_tag)==0)
 
277
            break;
 
278
        uac_state = uac_state->next;
 
279
    }
 
280
 
 
281
    /* Create new UAC state if we don't have one */
 
282
    if (uac_state == NULL) {
 
283
        uac_state = PJ_POOL_ZALLOC_T(dd->inv->dlg->pool, uac_state_t);
 
284
        uac_state->cseq = rdata->msg_info.cseq->cseq;
 
285
        uac_state->rseq = rseq - 1;
 
286
        pj_strdup(dd->inv->dlg->pool, &uac_state->tag, to_tag);
 
287
        uac_state->next = dd->uac_state_list;
 
288
        dd->uac_state_list = uac_state;
 
289
    }
 
290
 
 
291
    /* If this is from new INVITE transaction, reset UAC state. */
 
292
    if (rdata->msg_info.cseq->cseq != uac_state->cseq) {
 
293
        uac_state->cseq = rdata->msg_info.cseq->cseq;
 
294
        uac_state->rseq = rseq - 1;
 
295
    }
 
296
 
 
297
    /* Ignore provisional response retransmission */
 
298
    if (rseq <= uac_state->rseq) {
 
299
        /* This should have been handled before */
 
300
        return PJ_EIGNORED;
 
301
 
 
302
    /* Ignore provisional response with out-of-order RSeq */
 
303
    } else if (rseq != uac_state->rseq + 1) {
 
304
        PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
305
                 "Ignoring 100rel response because RSeq jump "
 
306
                 "(expecting %u, got %u)",
 
307
                 uac_state->rseq+1, rseq));
 
308
        return PJ_EIGNORED;
 
309
    }
 
310
 
 
311
    /* Update our RSeq */
 
312
    uac_state->rseq = rseq;
 
313
 
 
314
    /* Create PRACK */
 
315
    status = pjsip_dlg_create_request(dd->inv->dlg, &pjsip_prack_method,
 
316
                                      -1, &tdata);
 
317
    if (status != PJ_SUCCESS)
 
318
        return status;
 
319
 
 
320
    /* If this response is a forked response from a different call-leg,
 
321
     * update the req URI (https://trac.pjsip.org/repos/ticket/1364)
 
322
     */
 
323
    if (pj_stricmp(&uac_state->tag, &dd->inv->dlg->remote.info->tag)) {
 
324
        const pjsip_contact_hdr *mhdr;
 
325
 
 
326
        mhdr = (const pjsip_contact_hdr*)
 
327
               pjsip_msg_find_hdr(rdata->msg_info.msg,
 
328
                                  PJSIP_H_CONTACT, NULL);
 
329
        if (!mhdr || !mhdr->uri) {
 
330
            PJ_LOG(4,(dd->inv->dlg->obj_name,
 
331
                     "Ignoring 100rel response with no or "
 
332
                     "invalid Contact header"));
 
333
            pjsip_tx_data_dec_ref(tdata);
 
334
            return PJ_EIGNORED;
 
335
        }
 
336
        tdata->msg->line.req.uri = (pjsip_uri*)
 
337
                                   pjsip_uri_clone(tdata->pool, mhdr->uri);
 
338
    }
 
339
 
 
340
    /* Create RAck header */
 
341
    rack.ptr = rack_buf;
 
342
    rack.slen = pj_ansi_snprintf(rack.ptr, sizeof(rack_buf),
 
343
                                 "%u %u %.*s",
 
344
                                 rseq, rdata->msg_info.cseq->cseq,
 
345
                                 (int)tsx->method.name.slen,
 
346
                                 tsx->method.name.ptr);
 
347
    rack_hdr = pjsip_generic_string_hdr_create(tdata->pool, &RACK, &rack);
 
348
    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) rack_hdr);
 
349
 
 
350
    /* Done */
 
351
    *p_tdata = tdata;
 
352
 
 
353
    return PJ_SUCCESS;
 
354
}
 
355
 
 
356
 
 
357
/*
 
358
 * Send PRACK request.
 
359
 */
 
360
PJ_DEF(pj_status_t) pjsip_100rel_send_prack( pjsip_inv_session *inv,
 
361
                                             pjsip_tx_data *tdata)
 
362
{
 
363
    dlg_data *dd;
 
364
 
 
365
    dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
 
366
    PJ_ASSERT_ON_FAIL(dd != NULL, 
 
367
    {pjsip_tx_data_dec_ref(tdata); return PJSIP_ENOTINITIALIZED; });
 
368
 
 
369
    return pjsip_dlg_send_request(inv->dlg, tdata, 
 
370
                                  mod_100rel.mod.id, (void*) dd);
 
371
 
 
372
}
 
373
 
 
374
 
 
375
/*
 
376
 * Notify 100rel module that the invite session has been disconnected.
 
377
 */
 
378
PJ_DEF(pj_status_t) pjsip_100rel_end_session(pjsip_inv_session *inv)
 
379
{
 
380
    dlg_data *dd;
 
381
 
 
382
    dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
 
383
    if (!dd)
 
384
        return PJ_SUCCESS;
 
385
 
 
386
    /* Make sure we don't have pending transmission */
 
387
    if (dd->uas_state) {
 
388
        pj_assert(!dd->uas_state->retransmit_timer.id);
 
389
        pj_assert(pj_list_empty(&dd->uas_state->tx_data_list));
 
390
    }
 
391
 
 
392
    return PJ_SUCCESS;
 
393
}
 
394
 
 
395
 
 
396
static void parse_rack(const pj_str_t *rack,
 
397
                       pj_uint32_t *p_rseq, pj_int32_t *p_seq,
 
398
                       pj_str_t *p_method)
 
399
{
 
400
    const char *p = rack->ptr, *end = p + rack->slen;
 
401
    pj_str_t token;
 
402
 
 
403
    token.ptr = (char*)p;
 
404
    while (p < end && pj_isdigit(*p))
 
405
        ++p;
 
406
    token.slen = p - token.ptr;
 
407
    *p_rseq = pj_strtoul(&token);
 
408
 
 
409
    ++p;
 
410
    token.ptr = (char*)p;
 
411
    while (p < end && pj_isdigit(*p))
 
412
        ++p;
 
413
    token.slen = p - token.ptr;
 
414
    *p_seq = pj_strtoul(&token);
 
415
 
 
416
    ++p;
 
417
    if (p < end) {
 
418
        p_method->ptr = (char*)p;
 
419
        p_method->slen = end - p;
 
420
    } else {
 
421
        p_method->ptr = NULL;
 
422
        p_method->slen = 0;
 
423
    }
 
424
}
 
425
 
 
426
/* Clear all responses in the transmission list */
 
427
static void clear_all_responses(dlg_data *dd)
 
428
{
 
429
    tx_data_list_t *tl;
 
430
 
 
431
    tl = dd->uas_state->tx_data_list.next;
 
432
    while (tl != &dd->uas_state->tx_data_list) {
 
433
        pjsip_tx_data_dec_ref(tl->tdata);
 
434
        tl = tl->next;
 
435
    }
 
436
    pj_list_init(&dd->uas_state->tx_data_list);
 
437
}
 
438
 
 
439
 
 
440
/*
 
441
 * Handle incoming PRACK request.
 
442
 */
 
443
PJ_DEF(pj_status_t) pjsip_100rel_on_rx_prack( pjsip_inv_session *inv,
 
444
                                              pjsip_rx_data *rdata)
 
445
{
 
446
    dlg_data *dd;
 
447
    pjsip_transaction *tsx;
 
448
    pjsip_msg *msg;
 
449
    pjsip_generic_string_hdr *rack_hdr;
 
450
    pjsip_tx_data *tdata;
 
451
    pj_uint32_t rseq;
 
452
    pj_int32_t cseq;
 
453
    pj_str_t method;
 
454
    pj_status_t status;
 
455
 
 
456
    tsx = pjsip_rdata_get_tsx(rdata);
 
457
    pj_assert(tsx != NULL);
 
458
 
 
459
    msg = rdata->msg_info.msg;
 
460
 
 
461
    dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
 
462
    if (dd == NULL) {
 
463
        /* UAC sends us PRACK while we didn't send reliable provisional 
 
464
         * response. Respond with 400 (?) 
 
465
         */
 
466
        const pj_str_t reason = pj_str("Unexpected PRACK");
 
467
 
 
468
        status = pjsip_dlg_create_response(inv->dlg, rdata, 400, 
 
469
                                           &reason, &tdata);
 
470
        if (status == PJ_SUCCESS) {
 
471
            status = pjsip_dlg_send_response(inv->dlg, tsx, tdata);
 
472
        }
 
473
        return PJSIP_ENOTINITIALIZED;
 
474
    }
 
475
 
 
476
    /* Always reply with 200/OK for PRACK */
 
477
    status = pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
 
478
    if (status == PJ_SUCCESS) {
 
479
        status = pjsip_dlg_send_response(inv->dlg, tsx, tdata);
 
480
    }
 
481
 
 
482
    /* Ignore if we don't have pending transmission */
 
483
    if (dd->uas_state == NULL || pj_list_empty(&dd->uas_state->tx_data_list)) {
 
484
        PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
485
                  "PRACK ignored - no pending response"));
 
486
        return PJ_EIGNORED;
 
487
    }
 
488
 
 
489
    /* Find RAck header */
 
490
    rack_hdr = (pjsip_generic_string_hdr*)
 
491
               pjsip_msg_find_hdr_by_name(msg, &RACK, NULL);
 
492
    if (!rack_hdr) {
 
493
        /* RAck header not found */
 
494
        PJ_LOG(4,(dd->inv->dlg->obj_name, "No RAck header"));
 
495
        return PJSIP_EMISSINGHDR;
 
496
    }
 
497
 
 
498
    /* Parse RAck header */
 
499
    parse_rack(&rack_hdr->hvalue, &rseq, &cseq, &method);
 
500
 
 
501
 
 
502
    /* Match RAck against outgoing transmission */
 
503
    if (rseq == dd->uas_state->tx_data_list.next->rseq &&
 
504
        cseq == dd->uas_state->cseq)
 
505
    {
 
506
        /* 
 
507
         * Yes this PRACK matches outgoing transmission.
 
508
         */
 
509
        tx_data_list_t *tl = dd->uas_state->tx_data_list.next;
 
510
 
 
511
        if (dd->uas_state->retransmit_timer.id) {
 
512
            pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
 
513
                                     &dd->uas_state->retransmit_timer);
 
514
            dd->uas_state->retransmit_timer.id = PJ_FALSE;
 
515
        }
 
516
 
 
517
        /* Remove from the list */
 
518
        if (tl != &dd->uas_state->tx_data_list) {
 
519
            pj_list_erase(tl);
 
520
 
 
521
            /* Destroy the response */
 
522
            pjsip_tx_data_dec_ref(tl->tdata);
 
523
        }
 
524
 
 
525
        /* Schedule next packet */
 
526
        dd->uas_state->retransmit_count = 0;
 
527
        if (!pj_list_empty(&dd->uas_state->tx_data_list)) {
 
528
            on_retransmit(NULL, &dd->uas_state->retransmit_timer);
 
529
        }
 
530
 
 
531
    } else {
 
532
        /* No it doesn't match */
 
533
        PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
534
                 "Rx PRACK with no matching reliable response"));
 
535
        return PJ_EIGNORED;
 
536
    }
 
537
 
 
538
    return PJ_SUCCESS;
 
539
}
 
540
 
 
541
 
 
542
/*
 
543
 * This is retransmit timer callback, called initially to send the response,
 
544
 * and subsequently when the retransmission time elapses.
 
545
 */
 
546
static void on_retransmit(pj_timer_heap_t *timer_heap,
 
547
                          struct pj_timer_entry *entry)
 
548
{
 
549
    dlg_data *dd;
 
550
    tx_data_list_t *tl;
 
551
    pjsip_tx_data *tdata;
 
552
    pj_bool_t final;
 
553
    pj_time_val delay;
 
554
 
 
555
    PJ_UNUSED_ARG(timer_heap);
 
556
 
 
557
    dd = (dlg_data*) entry->user_data;
 
558
 
 
559
    entry->id = PJ_FALSE;
 
560
 
 
561
    ++dd->uas_state->retransmit_count;
 
562
    if (dd->uas_state->retransmit_count >= 7) {
 
563
        /* If a reliable provisional response is retransmitted for
 
564
           64*T1 seconds  without reception of a corresponding PRACK,
 
565
           the UAS SHOULD reject the original request with a 5xx 
 
566
           response.
 
567
        */
 
568
        pj_str_t reason = pj_str("Reliable response timed out");
 
569
        pj_status_t status;
 
570
 
 
571
        /* Clear all pending responses */
 
572
        clear_all_responses(dd);
 
573
 
 
574
        /* Send 500 response */
 
575
        status = pjsip_inv_end_session(dd->inv, 500, &reason, &tdata);
 
576
        if (status == PJ_SUCCESS) {
 
577
            pjsip_dlg_send_response(dd->inv->dlg, 
 
578
                                    dd->inv->invite_tsx,
 
579
                                    tdata);
 
580
        }
 
581
        return;
 
582
    }
 
583
 
 
584
    pj_assert(!pj_list_empty(&dd->uas_state->tx_data_list));
 
585
    tl = dd->uas_state->tx_data_list.next;
 
586
    tdata = tl->tdata;
 
587
 
 
588
    pjsip_tx_data_add_ref(tdata);
 
589
    final = tdata->msg->line.status.code >= 200;
 
590
 
 
591
    if (dd->uas_state->retransmit_count == 1) {
 
592
        pjsip_tsx_send_msg(dd->inv->invite_tsx, tdata);
 
593
    } else {
 
594
        pjsip_tsx_retransmit_no_state(dd->inv->invite_tsx, tdata);
 
595
    }
 
596
 
 
597
    if (final) {
 
598
        /* This is final response, which will be retransmitted by
 
599
         * UA layer. There's no more task to do, so clear the
 
600
         * transmission list and bail out.
 
601
         */
 
602
        clear_all_responses(dd);
 
603
        return;
 
604
    }
 
605
 
 
606
    /* Schedule next retransmission */
 
607
    if (dd->uas_state->retransmit_count < 6) {
 
608
        delay.sec = 0;
 
609
        delay.msec = (1 << dd->uas_state->retransmit_count) * 
 
610
                     pjsip_cfg()->tsx.t1;
 
611
        pj_time_val_normalize(&delay);
 
612
    } else {
 
613
        delay.sec = 1;
 
614
        delay.msec = 500;
 
615
    }
 
616
 
 
617
 
 
618
    pjsip_endpt_schedule_timer(dd->inv->dlg->endpt, 
 
619
                               &dd->uas_state->retransmit_timer,
 
620
                               &delay);
 
621
 
 
622
    entry->id = PJ_TRUE;
 
623
}
 
624
 
 
625
 
 
626
/* Clone response. */
 
627
static pjsip_tx_data *clone_tdata(dlg_data *dd,
 
628
                                  const pjsip_tx_data *src)
 
629
{
 
630
    pjsip_tx_data *dst;
 
631
    const pjsip_hdr *hsrc;
 
632
    pjsip_msg *msg;
 
633
    pj_status_t status;
 
634
 
 
635
    status = pjsip_endpt_create_tdata(dd->inv->dlg->endpt, &dst);
 
636
    if (status != PJ_SUCCESS)
 
637
        return NULL;
 
638
 
 
639
    msg = pjsip_msg_create(dst->pool, PJSIP_RESPONSE_MSG);
 
640
    dst->msg = msg;
 
641
    pjsip_tx_data_add_ref(dst);
 
642
 
 
643
    /* Duplicate status line */
 
644
    msg->line.status.code = src->msg->line.status.code;
 
645
    pj_strdup(dst->pool, &msg->line.status.reason, 
 
646
              &src->msg->line.status.reason);
 
647
 
 
648
    /* Duplicate all headers */
 
649
    hsrc = src->msg->hdr.next;
 
650
    while (hsrc != &src->msg->hdr) {
 
651
        pjsip_hdr *h = (pjsip_hdr*) pjsip_hdr_clone(dst->pool, hsrc);
 
652
        pjsip_msg_add_hdr(msg, h);
 
653
        hsrc = hsrc->next;
 
654
    }
 
655
 
 
656
    /* Duplicate message body */
 
657
    if (src->msg->body)
 
658
        msg->body = pjsip_msg_body_clone(dst->pool, src->msg->body);
 
659
 
 
660
    PJ_LOG(5,(dd->inv->dlg->obj_name,
 
661
             "Reliable response %s created",
 
662
             pjsip_tx_data_get_info(dst)));
 
663
 
 
664
    return dst;
 
665
}
 
666
 
 
667
 
 
668
/* Check if any pending response in transmission list has SDP */
 
669
static pj_bool_t has_sdp(dlg_data *dd)
 
670
{
 
671
    tx_data_list_t *tl;
 
672
 
 
673
    tl = dd->uas_state->tx_data_list.next;
 
674
    while (tl != &dd->uas_state->tx_data_list) {
 
675
            if (tl->tdata->msg->body)
 
676
                    return PJ_TRUE;
 
677
            tl = tl->next;
 
678
    }
 
679
 
 
680
    return PJ_FALSE;
 
681
}
 
682
 
 
683
 
 
684
/* Send response reliably */
 
685
PJ_DEF(pj_status_t) pjsip_100rel_tx_response(pjsip_inv_session *inv,
 
686
                                             pjsip_tx_data *tdata)
 
687
{
 
688
    pjsip_cseq_hdr *cseq_hdr;
 
689
    pjsip_generic_string_hdr *rseq_hdr;
 
690
    pjsip_require_hdr *req_hdr;
 
691
    int status_code;
 
692
    dlg_data *dd;
 
693
    pjsip_tx_data *old_tdata;
 
694
    pj_status_t status;
 
695
    
 
696
    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
 
697
                     PJSIP_ENOTRESPONSEMSG);
 
698
    
 
699
    status_code = tdata->msg->line.status.code;
 
700
    
 
701
    /* 100 response doesn't need PRACK */
 
702
    if (status_code == 100)
 
703
        return pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata);
 
704
    
 
705
 
 
706
    /* Get the 100rel data attached to this dialog */
 
707
    dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
 
708
    PJ_ASSERT_RETURN(dd != NULL, PJ_EINVALIDOP);
 
709
    
 
710
    
 
711
    /* Clone tdata.
 
712
     * We need to clone tdata because we may need to keep it in our
 
713
     * retransmission list, while the original dialog may modify it
 
714
     * if it wants to send another response.
 
715
     */
 
716
    old_tdata = tdata;
 
717
    tdata = clone_tdata(dd, old_tdata);
 
718
    pjsip_tx_data_dec_ref(old_tdata);
 
719
    
 
720
 
 
721
    /* Get CSeq header, and make sure this is INVITE response */
 
722
    cseq_hdr = (pjsip_cseq_hdr*)
 
723
                pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
 
724
    PJ_ASSERT_RETURN(cseq_hdr != NULL, PJ_EBUG);
 
725
    PJ_ASSERT_RETURN(cseq_hdr->method.id == PJSIP_INVITE_METHOD, 
 
726
        PJ_EINVALIDOP);
 
727
    
 
728
    /* Remove existing Require header */
 
729
    req_hdr = find_req_hdr(tdata->msg);
 
730
    if (req_hdr) {
 
731
        pj_list_erase(req_hdr);
 
732
    }
 
733
    
 
734
    /* Remove existing RSeq header */
 
735
    rseq_hdr = (pjsip_generic_string_hdr*)
 
736
        pjsip_msg_find_hdr_by_name(tdata->msg, &RSEQ, NULL);
 
737
    if (rseq_hdr)
 
738
        pj_list_erase(rseq_hdr);
 
739
    
 
740
    /* Different treatment for provisional and final response */
 
741
    if (status_code/100 == 2) {
 
742
        
 
743
        /* RFC 3262 Section 3: UAS Behavior:
 
744
    
 
745
          The UAS MAY send a final response to the initial request 
 
746
          before having received PRACKs for all unacknowledged 
 
747
          reliable provisional responses, unless the final response 
 
748
          is 2xx and any of the unacknowledged reliable provisional 
 
749
          responses contained a session description.  In that case, 
 
750
          it MUST NOT send a final response until those provisional 
 
751
          responses are acknowledged.
 
752
        */
 
753
        
 
754
        if (dd->uas_state && has_sdp(dd)) {
 
755
            /* Yes we have transmitted 1xx with SDP reliably.
 
756
             * In this case, must queue the 2xx response.
 
757
             */
 
758
            tx_data_list_t *tl;
 
759
            
 
760
            tl = PJ_POOL_ZALLOC_T(tdata->pool, tx_data_list_t);
 
761
            tl->tdata = tdata;
 
762
            tl->rseq = (pj_uint32_t)-1;
 
763
            pj_list_push_back(&dd->uas_state->tx_data_list, tl);
 
764
            
 
765
            /* Will send later */
 
766
            status = PJ_SUCCESS;
 
767
            
 
768
            PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
769
                      "2xx response will be sent after PRACK"));
 
770
            
 
771
        } else if (dd->uas_state) {
 
772
            /* 
 
773
            RFC 3262 Section 3: UAS Behavior:
 
774
 
 
775
            If the UAS does send a final response when reliable
 
776
            responses are still unacknowledged, it SHOULD NOT 
 
777
            continue to retransmit the unacknowledged reliable
 
778
            provisional responses, but it MUST be prepared to 
 
779
            process PRACK requests for those outstanding 
 
780
            responses.
 
781
            */
 
782
            
 
783
            PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
784
                      "No SDP sent so far, sending 2xx now"));
 
785
            
 
786
            /* Cancel the retransmit timer */
 
787
            if (dd->uas_state->retransmit_timer.id) {
 
788
                pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
 
789
                                         &dd->uas_state->retransmit_timer);
 
790
                dd->uas_state->retransmit_timer.id = PJ_FALSE;
 
791
            }
 
792
            
 
793
            /* Clear all pending responses (drop 'em) */
 
794
            clear_all_responses(dd);
 
795
            
 
796
            /* And transmit the 2xx response */
 
797
            status=pjsip_dlg_send_response(inv->dlg, 
 
798
                                           inv->invite_tsx, tdata);
 
799
            
 
800
        } else {
 
801
            /* We didn't send any reliable provisional response */
 
802
            
 
803
            /* Transmit the 2xx response */
 
804
            status=pjsip_dlg_send_response(inv->dlg, 
 
805
                                           inv->invite_tsx, tdata);
 
806
        }
 
807
        
 
808
    } else if (status_code >= 300) {
 
809
        
 
810
        /* 
 
811
        RFC 3262 Section 3: UAS Behavior:
 
812
 
 
813
        If the UAS does send a final response when reliable
 
814
        responses are still unacknowledged, it SHOULD NOT 
 
815
        continue to retransmit the unacknowledged reliable
 
816
        provisional responses, but it MUST be prepared to 
 
817
        process PRACK requests for those outstanding 
 
818
        responses.
 
819
        */
 
820
        
 
821
        /* Cancel the retransmit timer */
 
822
        if (dd->uas_state && dd->uas_state->retransmit_timer.id) {
 
823
            pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
 
824
                                     &dd->uas_state->retransmit_timer);
 
825
            dd->uas_state->retransmit_timer.id = PJ_FALSE;
 
826
            
 
827
            /* Clear all pending responses (drop 'em) */
 
828
            clear_all_responses(dd);
 
829
        }
 
830
        
 
831
        /* And transmit the 2xx response */
 
832
        status=pjsip_dlg_send_response(inv->dlg, 
 
833
                                       inv->invite_tsx, tdata);
 
834
        
 
835
    } else {
 
836
        /*
 
837
         * This is provisional response.
 
838
         */
 
839
        char rseq_str[32];
 
840
        pj_str_t rseq;
 
841
        tx_data_list_t *tl;
 
842
        
 
843
        /* Create UAS state if we don't have one */
 
844
        if (dd->uas_state == NULL) {
 
845
            dd->uas_state = PJ_POOL_ZALLOC_T(inv->dlg->pool,
 
846
                                             uas_state_t);
 
847
            dd->uas_state->cseq = cseq_hdr->cseq;
 
848
            dd->uas_state->rseq = pj_rand() % 0x7FFF;
 
849
            pj_list_init(&dd->uas_state->tx_data_list);
 
850
            dd->uas_state->retransmit_timer.user_data = dd;
 
851
            dd->uas_state->retransmit_timer.cb = &on_retransmit;
 
852
        }
 
853
        
 
854
        /* Check that CSeq match */
 
855
        PJ_ASSERT_RETURN(cseq_hdr->cseq == dd->uas_state->cseq,
 
856
                         PJ_EINVALIDOP);
 
857
        
 
858
        /* Add Require header */
 
859
        req_hdr = pjsip_require_hdr_create(tdata->pool);
 
860
        req_hdr->count = 1;
 
861
        req_hdr->values[0] = tag_100rel;
 
862
        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)req_hdr);
 
863
        
 
864
        /* Add RSeq header */
 
865
        pj_ansi_snprintf(rseq_str, sizeof(rseq_str), "%u",
 
866
                         dd->uas_state->rseq);
 
867
        rseq = pj_str(rseq_str);
 
868
        rseq_hdr = pjsip_generic_string_hdr_create(tdata->pool, 
 
869
                                                   &RSEQ, &rseq);
 
870
        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)rseq_hdr);
 
871
        
 
872
        /* Create list entry for this response */
 
873
        tl = PJ_POOL_ZALLOC_T(tdata->pool, tx_data_list_t);
 
874
        tl->tdata = tdata;
 
875
        tl->rseq = dd->uas_state->rseq++;
 
876
        
 
877
        /* Add to queue if there's pending response, otherwise
 
878
         * transmit immediately.
 
879
         */
 
880
        if (!pj_list_empty(&dd->uas_state->tx_data_list)) {
 
881
            
 
882
            int code = tdata->msg->line.status.code;
 
883
            
 
884
            /* Will send later */
 
885
            pj_list_push_back(&dd->uas_state->tx_data_list, tl);
 
886
            status = PJ_SUCCESS;
 
887
            
 
888
            PJ_LOG(4,(dd->inv->dlg->obj_name, 
 
889
                      "Reliable %d response enqueued (%d pending)", 
 
890
                      code, pj_list_size(&dd->uas_state->tx_data_list)));
 
891
            
 
892
        } else {
 
893
            pj_list_push_back(&dd->uas_state->tx_data_list, tl);
 
894
            
 
895
            dd->uas_state->retransmit_count = 0;
 
896
            on_retransmit(NULL, &dd->uas_state->retransmit_timer);
 
897
            status = PJ_SUCCESS;
 
898
        }
 
899
        
 
900
    }
 
901
    
 
902
    return status;
 
903
}
 
904
 
 
905