1 /* $Id$ */
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 static const pj_str_t tag_100rel = { "100rel", 6 };
54 static const pj_str_t RSEQ = { "RSeq", 4 };
55 static 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 */
mod_100rel_load(pjsip_endpoint * endpt)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
find_req_hdr(pjsip_msg * msg)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 */
pjsip_get_prack_method(void)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 */
pjsip_100rel_init_module(pjsip_endpoint * endpt)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 */
pjsip_100rel_attach(pjsip_inv_session * inv)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 */
pjsip_100rel_is_reliable(pjsip_rx_data * rdata)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 */
pjsip_100rel_create_prack(pjsip_inv_session * inv,pjsip_rx_data * rdata,pjsip_tx_data ** p_tdata)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 if (rack.slen < 1 || rack.slen >= (int)sizeof(rack_buf)) {
348 return PJ_ETOOSMALL;
349 }
350 rack_hdr = pjsip_generic_string_hdr_create(tdata->pool, &RACK, &rack);
351 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) rack_hdr);
352
353 /* Done */
354 *p_tdata = tdata;
355
356 return PJ_SUCCESS;
357 }
358
359
360 /*
361 * Send PRACK request.
362 */
pjsip_100rel_send_prack(pjsip_inv_session * inv,pjsip_tx_data * tdata)363 PJ_DEF(pj_status_t) pjsip_100rel_send_prack( pjsip_inv_session *inv,
364 pjsip_tx_data *tdata)
365 {
366 dlg_data *dd;
367
368 dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
369 PJ_ASSERT_ON_FAIL(dd != NULL,
370 {pjsip_tx_data_dec_ref(tdata); return PJSIP_ENOTINITIALIZED; });
371
372 return pjsip_dlg_send_request(inv->dlg, tdata,
373 mod_100rel.mod.id, (void*) dd);
374
375 }
376
377
378 /* Clear all responses in the transmission list */
clear_all_responses(dlg_data * dd)379 static void clear_all_responses(dlg_data *dd)
380 {
381 tx_data_list_t *tl;
382
383 tl = dd->uas_state->tx_data_list.next;
384 while (tl != &dd->uas_state->tx_data_list) {
385 pjsip_tx_data_dec_ref(tl->tdata);
386 tl = tl->next;
387 }
388 pj_list_init(&dd->uas_state->tx_data_list);
389 }
390
391 /*
392 * Notify 100rel module that the invite session has been disconnected.
393 */
pjsip_100rel_end_session(pjsip_inv_session * inv)394 PJ_DEF(pj_status_t) pjsip_100rel_end_session(pjsip_inv_session *inv)
395 {
396 dlg_data *dd;
397
398 dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
399 if (!dd)
400 return PJ_SUCCESS;
401
402 /* Make sure we don't have pending transmission */
403 if (dd->uas_state) {
404 /* Cancel the retransmit timer */
405 if (dd->uas_state->retransmit_timer.id) {
406 pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
407 &dd->uas_state->retransmit_timer);
408 dd->uas_state->retransmit_timer.id = PJ_FALSE;
409 }
410 if (!pj_list_empty(&dd->uas_state->tx_data_list)) {
411 /* Clear all pending responses (drop 'em) */
412 clear_all_responses(dd);
413 }
414 }
415
416 return PJ_SUCCESS;
417 }
418
419
parse_rack(const pj_str_t * rack,pj_uint32_t * p_rseq,pj_int32_t * p_seq,pj_str_t * p_method)420 static void parse_rack(const pj_str_t *rack,
421 pj_uint32_t *p_rseq, pj_int32_t *p_seq,
422 pj_str_t *p_method)
423 {
424 const char *p = rack->ptr, *end = p + rack->slen;
425 pj_str_t token;
426
427 token.ptr = (char*)p;
428 while (p < end && pj_isdigit(*p))
429 ++p;
430 token.slen = p - token.ptr;
431 *p_rseq = pj_strtoul(&token);
432
433 ++p;
434 token.ptr = (char*)p;
435 while (p < end && pj_isdigit(*p))
436 ++p;
437 token.slen = p - token.ptr;
438 *p_seq = pj_strtoul(&token);
439
440 ++p;
441 if (p < end) {
442 p_method->ptr = (char*)p;
443 p_method->slen = end - p;
444 } else {
445 p_method->ptr = NULL;
446 p_method->slen = 0;
447 }
448 }
449
450
451 /*
452 * Handle incoming PRACK request.
453 */
pjsip_100rel_on_rx_prack(pjsip_inv_session * inv,pjsip_rx_data * rdata)454 PJ_DEF(pj_status_t) pjsip_100rel_on_rx_prack( pjsip_inv_session *inv,
455 pjsip_rx_data *rdata)
456 {
457 dlg_data *dd;
458 pjsip_transaction *tsx;
459 pjsip_msg *msg;
460 pjsip_generic_string_hdr *rack_hdr;
461 pjsip_tx_data *tdata;
462 pj_uint32_t rseq;
463 pj_int32_t cseq;
464 pj_str_t method;
465 pj_status_t status;
466
467 tsx = pjsip_rdata_get_tsx(rdata);
468 pj_assert(tsx != NULL);
469
470 msg = rdata->msg_info.msg;
471
472 dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
473 if (dd == NULL) {
474 /* UAC sends us PRACK while we didn't send reliable provisional
475 * response. Respond with 400 (?)
476 */
477 const pj_str_t reason = pj_str("Unexpected PRACK");
478
479 status = pjsip_dlg_create_response(inv->dlg, rdata, 400,
480 &reason, &tdata);
481 if (status == PJ_SUCCESS) {
482 status = pjsip_dlg_send_response(inv->dlg, tsx, tdata);
483 }
484 return PJSIP_ENOTINITIALIZED;
485 }
486
487 /* Always reply with 200/OK for PRACK */
488 status = pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
489 if (status == PJ_SUCCESS) {
490 status = pjsip_dlg_send_response(inv->dlg, tsx, tdata);
491 }
492
493 /* Ignore if we don't have pending transmission */
494 if (dd->uas_state == NULL || pj_list_empty(&dd->uas_state->tx_data_list)) {
495 PJ_LOG(4,(dd->inv->dlg->obj_name,
496 "PRACK ignored - no pending response"));
497 return PJ_EIGNORED;
498 }
499
500 /* Find RAck header */
501 rack_hdr = (pjsip_generic_string_hdr*)
502 pjsip_msg_find_hdr_by_name(msg, &RACK, NULL);
503 if (!rack_hdr) {
504 /* RAck header not found */
505 PJ_LOG(4,(dd->inv->dlg->obj_name, "No RAck header"));
506 return PJSIP_EMISSINGHDR;
507 }
508
509 /* Parse RAck header */
510 parse_rack(&rack_hdr->hvalue, &rseq, &cseq, &method);
511
512
513 /* Match RAck against outgoing transmission */
514 if (rseq == dd->uas_state->tx_data_list.next->rseq &&
515 cseq == dd->uas_state->cseq)
516 {
517 /*
518 * Yes this PRACK matches outgoing transmission.
519 */
520 tx_data_list_t *tl = dd->uas_state->tx_data_list.next;
521
522 if (dd->uas_state->retransmit_timer.id) {
523 pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
524 &dd->uas_state->retransmit_timer);
525 dd->uas_state->retransmit_timer.id = PJ_FALSE;
526 }
527
528 /* Remove from the list */
529 if (tl != &dd->uas_state->tx_data_list) {
530 pj_list_erase(tl);
531
532 /* Destroy the response */
533 pjsip_tx_data_dec_ref(tl->tdata);
534 }
535
536 /* Schedule next packet */
537 dd->uas_state->retransmit_count = 0;
538 if (!pj_list_empty(&dd->uas_state->tx_data_list)) {
539 on_retransmit(NULL, &dd->uas_state->retransmit_timer);
540 }
541
542 } else {
543 /* No it doesn't match */
544 PJ_LOG(4,(dd->inv->dlg->obj_name,
545 "Rx PRACK with no matching reliable response"));
546 return PJ_EIGNORED;
547 }
548
549 return PJ_SUCCESS;
550 }
551
552
553 /*
554 * This is retransmit timer callback, called initially to send the response,
555 * and subsequently when the retransmission time elapses.
556 */
on_retransmit(pj_timer_heap_t * timer_heap,struct pj_timer_entry * entry)557 static void on_retransmit(pj_timer_heap_t *timer_heap,
558 struct pj_timer_entry *entry)
559 {
560 dlg_data *dd;
561 tx_data_list_t *tl;
562 pjsip_tx_data *tdata;
563 pj_bool_t final;
564 pj_time_val delay;
565
566 PJ_UNUSED_ARG(timer_heap);
567
568 dd = (dlg_data*) entry->user_data;
569
570 entry->id = PJ_FALSE;
571
572 ++dd->uas_state->retransmit_count;
573 if (dd->uas_state->retransmit_count >= 7) {
574 /* If a reliable provisional response is retransmitted for
575 64*T1 seconds without reception of a corresponding PRACK,
576 the UAS SHOULD reject the original request with a 5xx
577 response.
578 */
579 pj_str_t reason = pj_str("Reliable response timed out");
580 pj_status_t status;
581
582 /* Clear all pending responses */
583 clear_all_responses(dd);
584
585 /* Send 500 response */
586 status = pjsip_inv_end_session(dd->inv, 500, &reason, &tdata);
587 if (status == PJ_SUCCESS) {
588 pjsip_dlg_send_response(dd->inv->dlg,
589 dd->inv->invite_tsx,
590 tdata);
591 }
592 return;
593 }
594
595 pj_assert(!pj_list_empty(&dd->uas_state->tx_data_list));
596 tl = dd->uas_state->tx_data_list.next;
597 tdata = tl->tdata;
598
599 pjsip_tx_data_add_ref(tdata);
600 final = tdata->msg->line.status.code >= 200;
601
602 if (dd->uas_state->retransmit_count == 1) {
603 pj_status_t status;
604
605 status = pjsip_tsx_send_msg(dd->inv->invite_tsx, tdata);
606 if (status != PJ_SUCCESS) {
607 PJ_PERROR(3, (THIS_FILE, status,
608 "Failed to send message"));
609 return;
610 }
611 } else {
612 pjsip_tsx_retransmit_no_state(dd->inv->invite_tsx, tdata);
613 }
614
615 if (final) {
616 /* This is final response, which will be retransmitted by
617 * UA layer. There's no more task to do, so clear the
618 * transmission list and bail out.
619 */
620 clear_all_responses(dd);
621 return;
622 }
623
624 /* Schedule next retransmission */
625 if (dd->uas_state->retransmit_count < 6) {
626 delay.sec = 0;
627 delay.msec = (1 << dd->uas_state->retransmit_count) *
628 (long)pjsip_cfg()->tsx.t1;
629 pj_time_val_normalize(&delay);
630 } else {
631 delay.sec = 1;
632 delay.msec = 500;
633 }
634
635
636 pjsip_endpt_schedule_timer(dd->inv->dlg->endpt,
637 &dd->uas_state->retransmit_timer,
638 &delay);
639
640 entry->id = PJ_TRUE;
641 }
642
643
644
645 /* Check if any pending response in transmission list has SDP */
has_sdp(dlg_data * dd)646 static pj_bool_t has_sdp(dlg_data *dd)
647 {
648 tx_data_list_t *tl;
649
650 tl = dd->uas_state->tx_data_list.next;
651 while (tl != &dd->uas_state->tx_data_list) {
652 if (tl->tdata->msg->body)
653 return PJ_TRUE;
654 tl = tl->next;
655 }
656
657 return PJ_FALSE;
658 }
659
660
661 /* Send response reliably */
pjsip_100rel_tx_response(pjsip_inv_session * inv,pjsip_tx_data * tdata)662 PJ_DEF(pj_status_t) pjsip_100rel_tx_response(pjsip_inv_session *inv,
663 pjsip_tx_data *tdata)
664 {
665 pjsip_cseq_hdr *cseq_hdr;
666 pjsip_generic_string_hdr *rseq_hdr;
667 pjsip_require_hdr *req_hdr;
668 int status_code;
669 dlg_data *dd;
670 pjsip_tx_data *old_tdata;
671 pj_status_t status;
672
673 PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
674 PJSIP_ENOTRESPONSEMSG);
675
676 status_code = tdata->msg->line.status.code;
677
678 /* 100 response doesn't need PRACK */
679 if (status_code == 100)
680 return pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata);
681
682
683 /* Get the 100rel data attached to this dialog */
684 dd = (dlg_data*) inv->dlg->mod_data[mod_100rel.mod.id];
685 PJ_ASSERT_RETURN(dd != NULL, PJ_EINVALIDOP);
686
687
688 /* Clone tdata.
689 * We need to clone tdata because we may need to keep it in our
690 * retransmission list, while the original dialog may modify it
691 * if it wants to send another response.
692 */
693 old_tdata = tdata;
694 pjsip_tx_data_clone(old_tdata, 0, &tdata);
695 pjsip_tx_data_dec_ref(old_tdata);
696
697
698 /* Get CSeq header, and make sure this is INVITE response */
699 cseq_hdr = (pjsip_cseq_hdr*)
700 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
701 PJ_ASSERT_RETURN(cseq_hdr != NULL, PJ_EBUG);
702 PJ_ASSERT_RETURN(cseq_hdr->method.id == PJSIP_INVITE_METHOD,
703 PJ_EINVALIDOP);
704
705 /* Remove existing Require header */
706 req_hdr = find_req_hdr(tdata->msg);
707 if (req_hdr) {
708 pj_list_erase(req_hdr);
709 }
710
711 /* Remove existing RSeq header */
712 rseq_hdr = (pjsip_generic_string_hdr*)
713 pjsip_msg_find_hdr_by_name(tdata->msg, &RSEQ, NULL);
714 if (rseq_hdr)
715 pj_list_erase(rseq_hdr);
716
717 /* Different treatment for provisional and final response */
718 if (status_code/100 == 2) {
719
720 /* RFC 3262 Section 3: UAS Behavior:
721
722 The UAS MAY send a final response to the initial request
723 before having received PRACKs for all unacknowledged
724 reliable provisional responses, unless the final response
725 is 2xx and any of the unacknowledged reliable provisional
726 responses contained a session description. In that case,
727 it MUST NOT send a final response until those provisional
728 responses are acknowledged.
729 */
730
731 if (dd->uas_state && has_sdp(dd)) {
732 /* Yes we have transmitted 1xx with SDP reliably.
733 * In this case, must queue the 2xx response.
734 */
735 tx_data_list_t *tl;
736
737 tl = PJ_POOL_ZALLOC_T(tdata->pool, tx_data_list_t);
738 tl->tdata = tdata;
739 tl->rseq = (pj_uint32_t)-1;
740 pj_list_push_back(&dd->uas_state->tx_data_list, tl);
741
742 /* Will send later */
743 status = PJ_SUCCESS;
744
745 PJ_LOG(4,(dd->inv->dlg->obj_name,
746 "2xx response will be sent after PRACK"));
747
748 } else if (dd->uas_state) {
749 /*
750 RFC 3262 Section 3: UAS Behavior:
751
752 If the UAS does send a final response when reliable
753 responses are still unacknowledged, it SHOULD NOT
754 continue to retransmit the unacknowledged reliable
755 provisional responses, but it MUST be prepared to
756 process PRACK requests for those outstanding
757 responses.
758 */
759
760 PJ_LOG(4,(dd->inv->dlg->obj_name,
761 "No SDP sent so far, sending 2xx now"));
762
763 /* Cancel the retransmit timer */
764 if (dd->uas_state->retransmit_timer.id) {
765 pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
766 &dd->uas_state->retransmit_timer);
767 dd->uas_state->retransmit_timer.id = PJ_FALSE;
768 }
769
770 /* Clear all pending responses (drop 'em) */
771 clear_all_responses(dd);
772
773 /* And transmit the 2xx response */
774 status=pjsip_dlg_send_response(inv->dlg,
775 inv->invite_tsx, tdata);
776
777 } else {
778 /* We didn't send any reliable provisional response */
779
780 /* Transmit the 2xx response */
781 status=pjsip_dlg_send_response(inv->dlg,
782 inv->invite_tsx, tdata);
783 }
784
785 } else if (status_code >= 300) {
786
787 /*
788 RFC 3262 Section 3: UAS Behavior:
789
790 If the UAS does send a final response when reliable
791 responses are still unacknowledged, it SHOULD NOT
792 continue to retransmit the unacknowledged reliable
793 provisional responses, but it MUST be prepared to
794 process PRACK requests for those outstanding
795 responses.
796 */
797
798 /* Cancel the retransmit timer */
799 if (dd->uas_state && dd->uas_state->retransmit_timer.id) {
800 pjsip_endpt_cancel_timer(dd->inv->dlg->endpt,
801 &dd->uas_state->retransmit_timer);
802 dd->uas_state->retransmit_timer.id = PJ_FALSE;
803
804 /* Clear all pending responses (drop 'em) */
805 clear_all_responses(dd);
806 }
807
808 /* And transmit the 2xx response */
809 status=pjsip_dlg_send_response(inv->dlg,
810 inv->invite_tsx, tdata);
811
812 } else {
813 /*
814 * This is provisional response.
815 */
816 char rseq_str[32];
817 pj_str_t rseq;
818 tx_data_list_t *tl;
819
820 /* Create UAS state if we don't have one */
821 if (dd->uas_state == NULL) {
822 dd->uas_state = PJ_POOL_ZALLOC_T(inv->dlg->pool,
823 uas_state_t);
824 dd->uas_state->cseq = cseq_hdr->cseq;
825 dd->uas_state->rseq = (pj_rand() % 0x7FFF) + 1;
826 pj_list_init(&dd->uas_state->tx_data_list);
827 dd->uas_state->retransmit_timer.user_data = dd;
828 dd->uas_state->retransmit_timer.cb = &on_retransmit;
829 }
830
831 /* Check that CSeq match */
832 PJ_ASSERT_RETURN(cseq_hdr->cseq == dd->uas_state->cseq,
833 PJ_EINVALIDOP);
834
835 /* Add Require header */
836 req_hdr = pjsip_require_hdr_create(tdata->pool);
837 req_hdr->count = 1;
838 req_hdr->values[0] = tag_100rel;
839 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)req_hdr);
840
841 /* Add RSeq header */
842 pj_ansi_snprintf(rseq_str, sizeof(rseq_str), "%u",
843 dd->uas_state->rseq);
844 rseq = pj_str(rseq_str);
845 rseq_hdr = pjsip_generic_string_hdr_create(tdata->pool,
846 &RSEQ, &rseq);
847 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)rseq_hdr);
848
849 /* Create list entry for this response */
850 tl = PJ_POOL_ZALLOC_T(tdata->pool, tx_data_list_t);
851 tl->tdata = tdata;
852 tl->rseq = dd->uas_state->rseq++;
853
854 /* Add to queue if there's pending response, otherwise
855 * transmit immediately.
856 */
857 if (!pj_list_empty(&dd->uas_state->tx_data_list)) {
858
859 int code = tdata->msg->line.status.code;
860
861 /* Will send later */
862 pj_list_push_back(&dd->uas_state->tx_data_list, tl);
863 status = PJ_SUCCESS;
864
865 PJ_LOG(4,(dd->inv->dlg->obj_name,
866 "Reliable %d response enqueued (%d pending)",
867 code, pj_list_size(&dd->uas_state->tx_data_list)));
868
869 } else {
870 pj_list_push_back(&dd->uas_state->tx_data_list, tl);
871
872 dd->uas_state->retransmit_count = 0;
873 on_retransmit(NULL, &dd->uas_state->retransmit_timer);
874 status = PJ_SUCCESS;
875 }
876
877 }
878
879 return status;
880 }
881
882
883