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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjsip/src/pjsip-ua/sip_100rel.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: sip_100rel.c 3841 2011-10-24 09:28:13Z 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_strcmp(&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_strcmp(&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
 
}