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