~ubuntu-branches/ubuntu/raring/sflphone/raring

« back to all changes in this revision

Viewing changes to sflphone-common/libs/pjproject/pjsip/src/pjsip-ua/sip_100rel.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier
  • Date: 2011-11-25 13:24:12 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20111125132412-dc4qvhyosk74cd42
Tags: 1.0.1-4
Don't assume that arch:all packages will get built (closes: #649726)

Show diffs side-by-side

added added

removed removed

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