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/sip_dialog.h>
21 #include <pjsip/sip_ua_layer.h>
22 #include <pjsip/sip_errno.h>
23 #include <pjsip/sip_endpoint.h>
24 #include <pjsip/sip_parser.h>
25 #include <pjsip/sip_module.h>
26 #include <pjsip/sip_util.h>
27 #include <pjsip/sip_transaction.h>
28 #include <pj/assert.h>
29 #include <pj/os.h>
30 #include <pj/string.h>
31 #include <pj/pool.h>
32 #include <pj/guid.h>
33 #include <pj/rand.h>
34 #include <pj/array.h>
35 #include <pj/except.h>
36 #include <pj/hash.h>
37 #include <pj/log.h>
38 
39 #define THIS_FILE	"sip_dialog.c"
40 
41 long pjsip_dlg_lock_tls_id;
42 
43 /* Config */
44 pj_bool_t pjsip_include_allow_hdr_in_dlg = PJSIP_INCLUDE_ALLOW_HDR_IN_DLG;
45 
46 /* Contact header string */
47 static const pj_str_t HCONTACT = { "Contact", 7 };
48 
49 
pjsip_method_creates_dialog(const pjsip_method * m)50 PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m)
51 {
52     const pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 9}};
53     const pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}};
54     const pjsip_method notify = { PJSIP_OTHER_METHOD, {"NOTIFY", 6}};
55     const pjsip_method update = { PJSIP_OTHER_METHOD, {"UPDATE", 6}};
56 
57     return m->id == PJSIP_INVITE_METHOD ||
58 	   (pjsip_method_cmp(m, &subscribe)==0) ||
59 	   (pjsip_method_cmp(m, &refer)==0) ||
60 	   (pjsip_method_cmp(m, &notify)==0) ||
61 	   (pjsip_method_cmp(m, &update)==0);
62 }
63 
dlg_on_destroy(void * arg)64 static void dlg_on_destroy( void *arg )
65 {
66     pjsip_dialog *dlg = (pjsip_dialog *)arg;
67 
68     PJ_LOG(5,(dlg->obj_name, "Dialog destroyed!"));
69 
70     pjsip_endpt_release_pool(dlg->endpt, dlg->pool);
71 }
72 
create_dialog(pjsip_user_agent * ua,pj_grp_lock_t * grp_lock,pjsip_dialog ** p_dlg)73 static pj_status_t create_dialog( pjsip_user_agent *ua,
74 				  pj_grp_lock_t *grp_lock,
75 				  pjsip_dialog **p_dlg)
76 {
77     pjsip_endpoint *endpt;
78     pj_pool_t *pool;
79     pjsip_dialog *dlg;
80     pj_status_t status;
81 
82     endpt = pjsip_ua_get_endpt(ua);
83     if (!endpt)
84 	return PJ_EINVALIDOP;
85 
86     pool = pjsip_endpt_create_pool(endpt, "dlg%p",
87 				   PJSIP_POOL_LEN_DIALOG,
88 				   PJSIP_POOL_INC_DIALOG);
89     if (!pool)
90 	return PJ_ENOMEM;
91 
92     dlg = PJ_POOL_ZALLOC_T(pool, pjsip_dialog);
93     PJ_ASSERT_RETURN(dlg != NULL, PJ_ENOMEM);
94 
95     dlg->pool = pool;
96     pj_ansi_snprintf(dlg->obj_name, sizeof(dlg->obj_name), "dlg%p", dlg);
97     dlg->ua = ua;
98     dlg->endpt = endpt;
99     dlg->state = PJSIP_DIALOG_STATE_NULL;
100     dlg->add_allow = pjsip_include_allow_hdr_in_dlg;
101 
102     pj_list_init(&dlg->inv_hdr);
103     pj_list_init(&dlg->rem_cap_hdr);
104 
105     /* Init client authentication session. */
106     status = pjsip_auth_clt_init(&dlg->auth_sess, dlg->endpt,
107 				 dlg->pool, 0);
108     if (status != PJ_SUCCESS)
109 	goto on_error;
110 
111     if (grp_lock) {
112 	dlg->grp_lock_ = grp_lock;
113     } else {
114  	status = pj_grp_lock_create(pool, NULL, &dlg->grp_lock_);
115  	if (status != PJ_SUCCESS) {
116 	    goto on_error;
117  	}
118     }
119 
120     pj_grp_lock_add_ref(dlg->grp_lock_);
121     pj_grp_lock_add_handler(dlg->grp_lock_, pool, dlg, &dlg_on_destroy);
122 
123     pjsip_target_set_init(&dlg->target_set);
124 
125     *p_dlg = dlg;
126     return PJ_SUCCESS;
127 
128 on_error:
129     pjsip_endpt_release_pool(endpt, pool);
130     return status;
131 }
132 
destroy_dialog(pjsip_dialog * dlg,pj_bool_t unlock_mutex)133 static void destroy_dialog( pjsip_dialog *dlg, pj_bool_t unlock_mutex )
134 {
135     if (dlg->tp_sel.type != PJSIP_TPSELECTOR_NONE) {
136 	pjsip_tpselector_dec_ref(&dlg->tp_sel);
137 	pj_bzero(&dlg->tp_sel, sizeof(pjsip_tpselector));
138     }
139     pjsip_auth_clt_deinit(&dlg->auth_sess);
140 
141     pj_grp_lock_dec_ref(dlg->grp_lock_);
142 
143     if (unlock_mutex)
144 	pj_grp_lock_release(dlg->grp_lock_);
145 }
146 
147 /*
148  * Create an UAC dialog.
149  */
pjsip_dlg_create_uac(pjsip_user_agent * ua,const pj_str_t * local_uri,const pj_str_t * local_contact,const pj_str_t * remote_uri,const pj_str_t * target,pjsip_dialog ** p_dlg)150 PJ_DEF(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua,
151 					  const pj_str_t *local_uri,
152 					  const pj_str_t *local_contact,
153 					  const pj_str_t *remote_uri,
154 					  const pj_str_t *target,
155 					  pjsip_dialog **p_dlg)
156 {
157     pjsip_dlg_create_uac_param create_param;
158 
159     PJ_ASSERT_RETURN(ua && local_uri && remote_uri && p_dlg, PJ_EINVAL);
160 
161     pj_bzero(&create_param, sizeof(create_param));
162     create_param.ua = ua;
163     create_param.local_uri = *local_uri;
164     create_param.remote_uri = *remote_uri;
165     if (local_contact)
166 	create_param.local_contact = *local_contact;
167 
168     if (target)
169 	create_param.target = *target;
170 
171     return pjsip_dlg_create_uac2(&create_param, p_dlg);
172 }
173 
pjsip_dlg_create_uac2(const pjsip_dlg_create_uac_param * create_param,pjsip_dialog ** p_dlg)174 PJ_DEF(pj_status_t) pjsip_dlg_create_uac2(
175 				const pjsip_dlg_create_uac_param *create_param,
176 				pjsip_dialog **p_dlg)
177 {
178     pj_status_t status;
179     pj_str_t tmp;
180     pjsip_dialog *dlg;
181 
182     /* Check arguments. */
183     PJ_ASSERT_RETURN(create_param->ua && create_param->local_uri.slen &&
184 		     create_param->remote_uri.slen && p_dlg, PJ_EINVAL);
185 
186     /* Create dialog instance. */
187     status = create_dialog(create_param->ua, create_param->grp_lock, &dlg);
188     if (status != PJ_SUCCESS)
189 	return status;
190 
191     /* Parse target. */
192     pj_strdup_with_null(dlg->pool, &tmp, create_param->target.slen ?
193 			&create_param->target : &create_param->remote_uri);
194     dlg->target = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen, 0);
195     if (!dlg->target) {
196 	status = PJSIP_EINVALIDURI;
197 	goto on_error;
198     }
199 
200     /* Put any header param in the target URI into INVITE header list. */
201     if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) ||
202 	PJSIP_URI_SCHEME_IS_SIPS(dlg->target))
203     {
204 	pjsip_param *param;
205 	pjsip_sip_uri *uri = (pjsip_sip_uri*)pjsip_uri_get_uri(dlg->target);
206 
207 	param = uri->header_param.next;
208 	while (param != &uri->header_param) {
209 	    if (param->value.ptr) {
210 		pjsip_hdr *hdr;
211 		int c;
212 
213 		c = param->value.ptr[param->value.slen];
214 		param->value.ptr[param->value.slen] = '\0';
215 
216 		hdr = (pjsip_hdr*)
217 		    pjsip_parse_hdr(dlg->pool, &param->name, param->value.ptr,
218 				    param->value.slen, NULL);
219 
220 		param->value.ptr[param->value.slen] = (char)c;
221 
222 		if (hdr == NULL) {
223 		    status = PJSIP_EINVALIDURI;
224 		    goto on_error;
225 		}
226 		pj_list_push_back(&dlg->inv_hdr, hdr);
227 	    }
228 
229 	    param = param->next;
230 	}
231 
232 	/* Now must remove any header params from URL, since that would
233 	 * create another header in pjsip_endpt_create_request().
234 	 */
235 	pj_list_init(&uri->header_param);
236     }
237 
238     /* Add target to the target set */
239     pjsip_target_set_add_uri(&dlg->target_set, dlg->pool, dlg->target, 0);
240 
241     /* Init local info. */
242     dlg->local.info = pjsip_from_hdr_create(dlg->pool);
243     pj_strdup_with_null(dlg->pool, &dlg->local.info_str,
244 			&create_param->local_uri);
245     dlg->local.info->uri = pjsip_parse_uri(dlg->pool,
246 					   dlg->local.info_str.ptr,
247 					   dlg->local.info_str.slen, 0);
248     if (!dlg->local.info->uri) {
249 	status = PJSIP_EINVALIDURI;
250 	goto on_error;
251     }
252 
253     /* Generate local tag. */
254     pj_create_unique_string(dlg->pool, &dlg->local.info->tag);
255 
256     /* Calculate hash value of local tag. */
257     dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL,
258                                                &dlg->local.info->tag);
259 
260     /* Randomize local CSeq. */
261     dlg->local.first_cseq = pj_rand() & 0x7FFF;
262     dlg->local.cseq = dlg->local.first_cseq;
263 
264     /* Init local contact. */
265     pj_strdup_with_null(dlg->pool, &tmp,
266 		    create_param->local_contact.slen ?
267 		    &create_param->local_contact : &create_param->local_uri);
268     dlg->local.contact = (pjsip_contact_hdr*)
269 			 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr,
270 					 tmp.slen, NULL);
271     if (!dlg->local.contact) {
272 	status = PJSIP_EINVALIDURI;
273 	goto on_error;
274     }
275 
276     /* Init remote info. */
277     dlg->remote.info = pjsip_to_hdr_create(dlg->pool);
278     pj_strdup_with_null(dlg->pool, &dlg->remote.info_str,
279 			&create_param->remote_uri);
280     dlg->remote.info->uri = pjsip_parse_uri(dlg->pool,
281 					    dlg->remote.info_str.ptr,
282 					    dlg->remote.info_str.slen, 0);
283     if (!dlg->remote.info->uri) {
284 	status = PJSIP_EINVALIDURI;
285 	goto on_error;
286     }
287 
288     /* Remove header param from remote.info_str, if any */
289     if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) ||
290 	PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri))
291     {
292 	pjsip_sip_uri *sip_uri = (pjsip_sip_uri *)
293 				 pjsip_uri_get_uri(dlg->remote.info->uri);
294 	if (!pj_list_empty(&sip_uri->header_param)) {
295 	    pj_str_t tmp2;
296 
297 	    /* Remove all header param */
298 	    pj_list_init(&sip_uri->header_param);
299 
300 	    /* Print URI */
301 	    tmp2.ptr = (char*) pj_pool_alloc(dlg->pool,
302 	    				    dlg->remote.info_str.slen);
303 	    tmp2.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
304 				       sip_uri, tmp2.ptr,
305 				       dlg->remote.info_str.slen);
306 
307 	    if (tmp2.slen < 1) {
308 		status = PJSIP_EURITOOLONG;
309 		goto on_error;
310 	    }
311 
312 	    /* Assign remote.info_str */
313 	    dlg->remote.info_str = tmp2;
314 	}
315     }
316 
317 
318     /* Initialize remote's CSeq to -1. */
319     dlg->remote.cseq = dlg->remote.first_cseq = -1;
320 
321     /* Initial role is UAC. */
322     dlg->role = PJSIP_ROLE_UAC;
323 
324     /* Secure? */
325     dlg->secure = PJSIP_URI_SCHEME_IS_SIPS(dlg->target);
326 
327     /* Generate Call-ID header. */
328     dlg->call_id = pjsip_cid_hdr_create(dlg->pool);
329     pj_create_unique_string(dlg->pool, &dlg->call_id->id);
330 
331     /* Initial route set is empty. */
332     pj_list_init(&dlg->route_set);
333 
334     /* Register this dialog to user agent. */
335     status = pjsip_ua_register_dlg( create_param->ua, dlg );
336     if (status != PJ_SUCCESS)
337 	goto on_error;
338 
339     /* Done! */
340     *p_dlg = dlg;
341 
342     PJ_LOG(5,(dlg->obj_name, "UAC dialog created"));
343 
344     return PJ_SUCCESS;
345 
346 on_error:
347     destroy_dialog(dlg, PJ_FALSE);
348     return status;
349 }
350 
351 
352 /*
353  * Create UAS dialog.
354  */
create_uas_dialog(pjsip_user_agent * ua,pjsip_rx_data * rdata,const pj_str_t * contact,pj_bool_t inc_lock,pjsip_dialog ** p_dlg)355 pj_status_t create_uas_dialog( pjsip_user_agent *ua,
356 			       pjsip_rx_data *rdata,
357 			       const pj_str_t *contact,
358 			       pj_bool_t inc_lock,
359 			       pjsip_dialog **p_dlg)
360 {
361     pj_status_t status;
362     pjsip_hdr *pos = NULL;
363     pjsip_contact_hdr *contact_hdr;
364     pjsip_rr_hdr *rr;
365     pjsip_transaction *tsx = NULL;
366     pj_str_t tmp;
367     enum { TMP_LEN=PJSIP_MAX_URL_SIZE };
368     pj_ssize_t len;
369     pjsip_dialog *dlg;
370     pj_bool_t lock_incremented = PJ_FALSE;
371 
372     /* Check arguments. */
373     PJ_ASSERT_RETURN(ua && rdata && p_dlg, PJ_EINVAL);
374 
375     /* rdata must have request message. */
376     PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
377 		     PJSIP_ENOTREQUESTMSG);
378 
379     /* Request must not have To tag.
380      * This should have been checked in the user agent (or application?).
381      */
382     PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen == 0, PJ_EINVALIDOP);
383 
384     /* The request must be a dialog establishing request. */
385     PJ_ASSERT_RETURN(
386 	pjsip_method_creates_dialog(&rdata->msg_info.msg->line.req.method),
387 	PJ_EINVALIDOP);
388 
389     /* Create dialog instance. */
390     status = create_dialog(ua, NULL, &dlg);
391     if (status != PJ_SUCCESS)
392 	return status;
393 
394     /* Temprary string for getting the string representation of
395      * both local and remote URI.
396      */
397     tmp.ptr = (char*) pj_pool_alloc(rdata->tp_info.pool, TMP_LEN);
398 
399     /* Init local info from the To header. */
400     dlg->local.info = (pjsip_fromto_hdr*)
401     		      pjsip_hdr_clone(dlg->pool, rdata->msg_info.to);
402     pjsip_fromto_hdr_set_from(dlg->local.info);
403 
404     /* Generate local tag. */
405     pj_create_unique_string(dlg->pool, &dlg->local.info->tag);
406 
407 
408     /* Print the local info. */
409     len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
410 			  dlg->local.info->uri, tmp.ptr, TMP_LEN);
411     if (len < 1) {
412 	pj_ansi_strcpy(tmp.ptr, "<-error: uri too long->");
413 	tmp.slen = pj_ansi_strlen(tmp.ptr);
414     } else
415 	tmp.slen = len;
416 
417     /* Save the local info. */
418     pj_strdup(dlg->pool, &dlg->local.info_str, &tmp);
419 
420     /* Calculate hash value of local tag. */
421     dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->local.info->tag);
422 
423 
424     /* Randomize local cseq */
425     dlg->local.first_cseq = pj_rand() & 0x7FFF;
426     dlg->local.cseq = dlg->local.first_cseq;
427 
428     /* Init local contact. */
429     /* TODO:
430      *  Section 12.1.1, paragraph about using SIPS URI in Contact.
431      *  If the request that initiated the dialog contained a SIPS URI
432      *  in the Request-URI or in the top Record-Route header field value,
433      *  if there was any, or the Contact header field if there was no
434      *  Record-Route header field, the Contact header field in the response
435      *  MUST be a SIPS URI.
436      */
437     if (contact) {
438 	pj_str_t tmp2;
439 
440 	pj_strdup_with_null(dlg->pool, &tmp2, contact);
441 	dlg->local.contact = (pjsip_contact_hdr*)
442 			     pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp2.ptr,
443 					     tmp2.slen, NULL);
444 	if (!dlg->local.contact) {
445 	    status = PJSIP_EINVALIDURI;
446 	    goto on_error;
447 	}
448 
449     } else {
450 	dlg->local.contact = pjsip_contact_hdr_create(dlg->pool);
451 	dlg->local.contact->uri = dlg->local.info->uri;
452     }
453 
454     /* Init remote info from the From header. */
455     dlg->remote.info = (pjsip_fromto_hdr*)
456     		       pjsip_hdr_clone(dlg->pool, rdata->msg_info.from);
457     pjsip_fromto_hdr_set_to(dlg->remote.info);
458 
459     /* Print the remote info. */
460     len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
461 			  dlg->remote.info->uri, tmp.ptr, TMP_LEN);
462     if (len < 1) {
463 	pj_ansi_strcpy(tmp.ptr, "<-error: uri too long->");
464 	tmp.slen = pj_ansi_strlen(tmp.ptr);
465     } else
466 	tmp.slen = len;
467 
468     /* Save the remote info. */
469     pj_strdup(dlg->pool, &dlg->remote.info_str, &tmp);
470 
471     /* Save initial destination host from transport's info */
472     pj_strdup(dlg->pool, &dlg->initial_dest,
473     	      &rdata->tp_info.transport->remote_name.host);
474 
475 
476     /* Init remote's contact from Contact header.
477      * Iterate the Contact URI until we find sip: or sips: scheme.
478      */
479     do {
480 	contact_hdr = (pjsip_contact_hdr*)
481 		      pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
482 				         pos);
483 	if (contact_hdr) {
484 	    if (!contact_hdr->uri ||
485 		(!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) &&
486 		 !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)))
487 	    {
488 		pos = (pjsip_hdr*)contact_hdr->next;
489 		if (pos == &rdata->msg_info.msg->hdr)
490 		    contact_hdr = NULL;
491 	    } else {
492 		break;
493 	    }
494 	}
495     } while (contact_hdr);
496 
497     if (!contact_hdr) {
498 	status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);
499 	goto on_error;
500     }
501 
502     dlg->remote.contact = (pjsip_contact_hdr*)
503     			  pjsip_hdr_clone(dlg->pool, (pjsip_hdr*)contact_hdr);
504 
505     /* Init remote's CSeq from CSeq header */
506     dlg->remote.cseq = dlg->remote.first_cseq = rdata->msg_info.cseq->cseq;
507 
508     /* Set initial target to remote's Contact. */
509     dlg->target = dlg->remote.contact->uri;
510 
511     /* Initial role is UAS */
512     dlg->role = PJSIP_ROLE_UAS;
513 
514     /* Secure?
515      *  RFC 3261 Section 12.1.1:
516      *  If the request arrived over TLS, and the Request-URI contained a
517      *  SIPS URI, the 'secure' flag is set to TRUE.
518      */
519     dlg->secure = PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport) &&
520 		  PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri);
521 
522     /* Call-ID */
523     dlg->call_id = (pjsip_cid_hdr*)
524     		   pjsip_hdr_clone(dlg->pool, rdata->msg_info.cid);
525 
526     /* Route set.
527      *  RFC 3261 Section 12.1.1:
528      *  The route set MUST be set to the list of URIs in the Record-Route
529      *  header field from the request, taken in order and preserving all URI
530      *  parameters. If no Record-Route header field is present in the request,
531      * the route set MUST be set to the empty set.
532      */
533     pj_list_init(&dlg->route_set);
534     rr = rdata->msg_info.record_route;
535     while (rr != NULL) {
536 	pjsip_route_hdr *route;
537 
538 	/* Clone the Record-Route, change the type to Route header. */
539 	route = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, rr);
540 	pjsip_routing_hdr_set_route(route);
541 
542 	/* Add to route set. */
543 	pj_list_push_back(&dlg->route_set, route);
544 
545 	/* Find next Record-Route header. */
546 	rr = rr->next;
547 	if (rr == (void*)&rdata->msg_info.msg->hdr)
548 	    break;
549 	rr = (pjsip_route_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg,
550 						   PJSIP_H_RECORD_ROUTE, rr);
551     }
552     dlg->route_set_frozen = PJ_TRUE;
553 
554     /* Increment the dialog's lock since tsx may cause the dialog to be
555      * destroyed prematurely (such as in case of transport error).
556      */
557     if (inc_lock) {
558         pjsip_dlg_inc_lock(dlg);
559         lock_incremented = PJ_TRUE;
560     }
561 
562     /* Create UAS transaction for this request. */
563     status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx);
564     if (status != PJ_SUCCESS)
565 	goto on_error;
566 
567     /* Associate this dialog to the transaction. */
568     tsx->mod_data[dlg->ua->id] = dlg;
569 
570     /* Increment tsx counter */
571     ++dlg->tsx_count;
572 
573     /* Calculate hash value of remote tag. */
574     dlg->remote.tag_hval = pj_hash_calc_tolower(0, NULL, &dlg->remote.info->tag);
575 
576     /* Update remote capabilities info */
577     pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, PJ_TRUE);
578 
579     /* Register this dialog to user agent. */
580     status = pjsip_ua_register_dlg( ua, dlg );
581     if (status != PJ_SUCCESS)
582 	goto on_error;
583 
584     /* Put this dialog in rdata's mod_data */
585     rdata->endpt_info.mod_data[ua->id] = dlg;
586 
587     PJ_TODO(DIALOG_APP_TIMER);
588 
589     /* Feed the first request to the transaction. */
590     pjsip_tsx_recv_msg(tsx, rdata);
591 
592     /* Done. */
593     *p_dlg = dlg;
594     PJ_LOG(5,(dlg->obj_name, "UAS dialog created"));
595     return PJ_SUCCESS;
596 
597 on_error:
598     if (tsx) {
599 	pjsip_tsx_terminate(tsx, 500);
600 	pj_assert(dlg->tsx_count>0);
601 	--dlg->tsx_count;
602     }
603 
604     if (lock_incremented) {
605         pjsip_dlg_dec_lock(dlg);
606     } else {
607         destroy_dialog(dlg, PJ_FALSE);
608     }
609 
610     return status;
611 }
612 
613 
614 #if !DEPRECATED_FOR_TICKET_1902
615 /*
616  * Create UAS dialog.
617  */
pjsip_dlg_create_uas(pjsip_user_agent * ua,pjsip_rx_data * rdata,const pj_str_t * contact,pjsip_dialog ** p_dlg)618 PJ_DEF(pj_status_t) pjsip_dlg_create_uas(   pjsip_user_agent *ua,
619 					    pjsip_rx_data *rdata,
620 					    const pj_str_t *contact,
621 					    pjsip_dialog **p_dlg)
622 {
623     return create_uas_dialog(ua, rdata, contact, PJ_FALSE, p_dlg);
624 }
625 #endif
626 
627 
628 /*
629  * Create UAS dialog and increase its session count.
630  */
631 PJ_DEF(pj_status_t)
pjsip_dlg_create_uas_and_inc_lock(pjsip_user_agent * ua,pjsip_rx_data * rdata,const pj_str_t * contact,pjsip_dialog ** p_dlg)632 pjsip_dlg_create_uas_and_inc_lock(    pjsip_user_agent *ua,
633 				      pjsip_rx_data *rdata,
634 				      const pj_str_t *contact,
635 				      pjsip_dialog **p_dlg)
636 {
637     return create_uas_dialog(ua, rdata, contact, PJ_TRUE, p_dlg);
638 }
639 
640 
641 /*
642  * Bind dialog to a specific transport/listener.
643  */
pjsip_dlg_set_transport(pjsip_dialog * dlg,const pjsip_tpselector * sel)644 PJ_DEF(pj_status_t) pjsip_dlg_set_transport( pjsip_dialog *dlg,
645 					     const pjsip_tpselector *sel)
646 {
647     /* Validate */
648     PJ_ASSERT_RETURN(dlg && sel, PJ_EINVAL);
649 
650     /* Start locking the dialog. */
651     pjsip_dlg_inc_lock(dlg);
652 
653     /* Decrement reference counter of previous transport selector */
654     pjsip_tpselector_dec_ref(&dlg->tp_sel);
655 
656     /* Copy transport selector structure .*/
657     pj_memcpy(&dlg->tp_sel, sel, sizeof(*sel));
658 
659     /* Increment reference counter */
660     pjsip_tpselector_add_ref(&dlg->tp_sel);
661 
662     /* Unlock dialog. */
663     pjsip_dlg_dec_lock(dlg);
664 
665     return PJ_SUCCESS;
666 }
667 
668 /*
669  * Set "sent-by" field of Via header.
670  */
pjsip_dlg_set_via_sent_by(pjsip_dialog * dlg,pjsip_host_port * via_addr,pjsip_transport * via_tp)671 PJ_DEF(pj_status_t) pjsip_dlg_set_via_sent_by( pjsip_dialog *dlg,
672 				               pjsip_host_port *via_addr,
673                                                pjsip_transport *via_tp)
674 {
675     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
676 
677     if (!via_addr)
678         pj_bzero(&dlg->via_addr, sizeof(dlg->via_addr));
679     else {
680         if (pj_strcmp(&dlg->via_addr.host, &via_addr->host))
681             pj_strdup(dlg->pool, &dlg->via_addr.host, &via_addr->host);
682         dlg->via_addr.port = via_addr->port;
683     }
684     dlg->via_tp = via_tp;
685 
686     return PJ_SUCCESS;
687 }
688 
689 
690 /*
691  * Create forked dialog from a response.
692  */
pjsip_dlg_fork(const pjsip_dialog * first_dlg,const pjsip_rx_data * rdata,pjsip_dialog ** new_dlg)693 PJ_DEF(pj_status_t) pjsip_dlg_fork( const pjsip_dialog *first_dlg,
694 				    const pjsip_rx_data *rdata,
695 				    pjsip_dialog **new_dlg )
696 {
697     pjsip_dialog *dlg;
698     const pjsip_msg *msg = rdata->msg_info.msg;
699     const pjsip_hdr *end_hdr, *hdr;
700     const pjsip_contact_hdr *contact;
701     pj_status_t status;
702 
703     /* Check arguments. */
704     PJ_ASSERT_RETURN(first_dlg && rdata && new_dlg, PJ_EINVAL);
705 
706     /* rdata must be response message. */
707     PJ_ASSERT_RETURN(msg->type == PJSIP_RESPONSE_MSG,
708 		     PJSIP_ENOTRESPONSEMSG);
709 
710     /* Status code MUST be 1xx (but not 100), or 2xx */
711     status = msg->line.status.code;
712     PJ_ASSERT_RETURN( (status/100==1 && status!=100) ||
713 		      (status/100==2), PJ_EBUG);
714 
715     /* To tag must present in the response. */
716     PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen != 0, PJSIP_EMISSINGTAG);
717 
718     /* Find Contact header in the response */
719     contact = (const pjsip_contact_hdr*)
720 	      pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL);
721     if (contact == NULL || contact->uri == NULL)
722 	return PJSIP_EMISSINGHDR;
723 
724     /* Create the dialog. */
725     status = create_dialog((pjsip_user_agent*)first_dlg->ua, NULL, &dlg);
726     if (status != PJ_SUCCESS)
727 	return status;
728 
729     /* Set remote target from the response. */
730     dlg->target = (pjsip_uri*) pjsip_uri_clone(dlg->pool, contact->uri);
731 
732     /* Clone local info. */
733     dlg->local.info = (pjsip_fromto_hdr*)
734     		      pjsip_hdr_clone(dlg->pool, first_dlg->local.info);
735 
736     /* Clone local tag. */
737     pj_strdup(dlg->pool, &dlg->local.info->tag, &first_dlg->local.info->tag);
738     dlg->local.tag_hval = first_dlg->local.tag_hval;
739 
740     /* Clone local CSeq. */
741     dlg->local.first_cseq = first_dlg->local.first_cseq;
742     dlg->local.cseq = first_dlg->local.cseq;
743 
744     /* Clone local Contact. */
745     dlg->local.contact = (pjsip_contact_hdr*)
746     			 pjsip_hdr_clone(dlg->pool, first_dlg->local.contact);
747 
748     /* Clone remote info. */
749     dlg->remote.info = (pjsip_fromto_hdr*)
750     		       pjsip_hdr_clone(dlg->pool, first_dlg->remote.info);
751 
752     /* Set remote tag from the response. */
753     pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag);
754 
755     /* Initialize remote's CSeq to -1. */
756     dlg->remote.cseq = dlg->remote.first_cseq = -1;
757 
758     /* Initial role is UAC. */
759     dlg->role = PJSIP_ROLE_UAC;
760 
761     /* Dialog state depends on the response. */
762     status = msg->line.status.code/100;
763     if (status == 1 || status == 2)
764 	dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED;
765     else {
766 	pj_assert(!"Invalid status code");
767 	dlg->state = PJSIP_DIALOG_STATE_NULL;
768     }
769 
770     /* Secure? */
771     dlg->secure = PJSIP_URI_SCHEME_IS_SIPS(dlg->target);
772 
773     /* Clone Call-ID header. */
774     dlg->call_id = (pjsip_cid_hdr*)
775     		   pjsip_hdr_clone(dlg->pool, first_dlg->call_id);
776 
777     /* Get route-set from the response. */
778     pj_list_init(&dlg->route_set);
779     end_hdr = &msg->hdr;
780     for (hdr=msg->hdr.prev; hdr!=end_hdr; hdr=hdr->prev) {
781 	if (hdr->type == PJSIP_H_RECORD_ROUTE) {
782 	    pjsip_route_hdr *r;
783 	    r = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, hdr);
784 	    pjsip_routing_hdr_set_route(r);
785 	    pj_list_push_back(&dlg->route_set, r);
786 	}
787     }
788 
789     //dlg->route_set_frozen = PJ_TRUE;
790 
791     /* Clone client authentication session. */
792     status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess,
793 				  &first_dlg->auth_sess);
794     if (status != PJ_SUCCESS)
795 	goto on_error;
796 
797     /* Register this dialog to user agent. */
798     status = pjsip_ua_register_dlg(dlg->ua, dlg );
799     if (status != PJ_SUCCESS)
800 	goto on_error;
801 
802 
803     /* Done! */
804     *new_dlg = dlg;
805 
806     PJ_LOG(5,(dlg->obj_name, "Forked dialog created"));
807     return PJ_SUCCESS;
808 
809 on_error:
810     destroy_dialog(dlg, PJ_FALSE);
811     return status;
812 }
813 
814 
815 /*
816  * Unregister and destroy dialog.
817  */
unregister_and_destroy_dialog(pjsip_dialog * dlg,pj_bool_t unlock_mutex)818 static pj_status_t unregister_and_destroy_dialog( pjsip_dialog *dlg,
819 						  pj_bool_t unlock_mutex )
820 {
821     pj_status_t status;
822 
823     /* Lock must have been held. */
824 
825     /* Check dialog state. */
826     /* Number of sessions must be zero. */
827     PJ_ASSERT_RETURN(dlg->sess_count==0, PJ_EINVALIDOP);
828 
829     /* MUST not have pending transactions. */
830     PJ_ASSERT_RETURN(dlg->tsx_count==0, PJ_EINVALIDOP);
831 
832     /* Unregister from user agent, if it has been registered (see #1924) */
833     if (dlg->dlg_set) {
834 	status = pjsip_ua_unregister_dlg(dlg->ua, dlg);
835 	if (status != PJ_SUCCESS) {
836 	    pj_assert(!"Unexpected failed unregistration!");
837 	    return status;
838 	}
839     }
840 
841     /* Destroy this dialog. */
842     destroy_dialog(dlg, unlock_mutex);
843 
844     return PJ_SUCCESS;
845 }
846 
847 
848 /*
849  * Forcefully terminate dialog.
850  */
pjsip_dlg_terminate(pjsip_dialog * dlg)851 PJ_DEF(pj_status_t) pjsip_dlg_terminate( pjsip_dialog *dlg )
852 {
853     /* Number of sessions must be zero. */
854     PJ_ASSERT_RETURN(dlg->sess_count==0, PJ_EINVALIDOP);
855 
856     /* MUST not have pending transactions. */
857     PJ_ASSERT_RETURN(dlg->tsx_count==0, PJ_EINVALIDOP);
858 
859     return unregister_and_destroy_dialog(dlg, PJ_FALSE);
860 }
861 
862 
863 /*
864  * Set route_set
865  */
pjsip_dlg_set_route_set(pjsip_dialog * dlg,const pjsip_route_hdr * route_set)866 PJ_DEF(pj_status_t) pjsip_dlg_set_route_set( pjsip_dialog *dlg,
867 					     const pjsip_route_hdr *route_set )
868 {
869     pjsip_route_hdr *r;
870 
871     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
872 
873     pjsip_dlg_inc_lock(dlg);
874 
875     /* Clear route set. */
876     pj_list_init(&dlg->route_set);
877 
878     if (!route_set) {
879 	pjsip_dlg_dec_lock(dlg);
880 	return PJ_SUCCESS;
881     }
882 
883     r = route_set->next;
884     while (r != route_set) {
885 	pjsip_route_hdr *new_r;
886 
887 	new_r = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, r);
888 	pj_list_push_back(&dlg->route_set, new_r);
889 
890 	r = r->next;
891     }
892 
893     pjsip_dlg_dec_lock(dlg);
894     return PJ_SUCCESS;
895 }
896 
897 
898 /*
899  * Increment session counter.
900  */
pjsip_dlg_inc_session(pjsip_dialog * dlg,pjsip_module * mod)901 PJ_DEF(pj_status_t) pjsip_dlg_inc_session( pjsip_dialog *dlg,
902 					   pjsip_module *mod )
903 {
904     PJ_ASSERT_RETURN(dlg && mod, PJ_EINVAL);
905 
906     pj_log_push_indent();
907 
908     pjsip_dlg_inc_lock(dlg);
909     ++dlg->sess_count;
910     pjsip_dlg_dec_lock(dlg);
911 
912     PJ_LOG(5,(dlg->obj_name, "Session count inc to %d by %.*s",
913 	      dlg->sess_count, (int)mod->name.slen, mod->name.ptr));
914 
915     pj_log_pop_indent();
916     return PJ_SUCCESS;
917 }
918 
919 /*
920  * Lock dialog and increment session count temporarily
921  * to prevent it from being deleted. In addition, it must lock
922  * the user agent's dialog table first, to prevent deadlock.
923  */
pjsip_dlg_inc_lock(pjsip_dialog * dlg)924 PJ_DEF(void) pjsip_dlg_inc_lock(pjsip_dialog *dlg)
925 {
926     PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_inc_lock(), sess_count=%d",
927 	      dlg->sess_count));
928 
929     pj_grp_lock_acquire(dlg->grp_lock_);
930     dlg->sess_count++;
931 
932     PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_inc_lock(), sess_count=%d",
933 	      dlg->sess_count));
934 }
935 
936 /* Try to acquire dialog's group lock, but bail out if group lock can not be
937  * acquired immediately.
938  */
pjsip_dlg_try_inc_lock(pjsip_dialog * dlg)939 PJ_DEF(pj_status_t) pjsip_dlg_try_inc_lock(pjsip_dialog *dlg)
940 {
941     pj_status_t status;
942 
943     PJ_LOG(6,(dlg->obj_name,"Entering pjsip_dlg_try_inc_lock(), sess_count=%d",
944 	      dlg->sess_count));
945 
946     status = pj_grp_lock_tryacquire(dlg->grp_lock_);
947     if (status != PJ_SUCCESS) {
948 	PJ_LOG(6,(dlg->obj_name, "pjsip_dlg_try_inc_lock() failed"));
949 	return status;
950     }
951 
952     dlg->sess_count++;
953 
954     PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_try_inc_lock(), sess_count=%d",
955 	      dlg->sess_count));
956 
957     return PJ_SUCCESS;
958 }
959 
960 
961 /*
962  * Unlock dialog and decrement reference counter.
963  * It may delete the dialog!
964  */
pjsip_dlg_dec_lock(pjsip_dialog * dlg)965 PJ_DEF(void) pjsip_dlg_dec_lock(pjsip_dialog *dlg)
966 {
967     PJ_ASSERT_ON_FAIL(dlg!=NULL, return);
968 
969     PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_dec_lock(), sess_count=%d",
970 	      dlg->sess_count));
971 
972     pj_assert(dlg->sess_count > 0);
973     --dlg->sess_count;
974 
975     if (dlg->sess_count==0 && dlg->tsx_count==0) {
976 	pj_grp_lock_release(dlg->grp_lock_);
977 	pj_grp_lock_acquire(dlg->grp_lock_);
978 	/* We are holding the dialog group lock here, so before we destroy
979 	 * the dialog, make sure that we unlock it first to avoid
980 	 * undefined behaviour on some platforms. See ticket #1886.
981 	 */
982 	unregister_and_destroy_dialog(dlg, PJ_TRUE);
983     } else {
984 	pj_grp_lock_release(dlg->grp_lock_);
985     }
986 
987     PJ_LOG(6,(THIS_FILE, "Leaving pjsip_dlg_dec_lock() (dlg=%p)", dlg));
988 }
989 
990 
991 /*
992  * Decrement session count.
993  */
pjsip_dlg_dec_session(pjsip_dialog * dlg,pjsip_module * mod)994 PJ_DEF(pj_status_t) pjsip_dlg_dec_session( pjsip_dialog *dlg,
995 					   pjsip_module *mod)
996 {
997     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
998 
999     pj_log_push_indent();
1000 
1001     PJ_LOG(5,(dlg->obj_name, "Session count dec to %d by %.*s",
1002 	      dlg->sess_count-1, (int)mod->name.slen, mod->name.ptr));
1003 
1004     pjsip_dlg_inc_lock(dlg);
1005     --dlg->sess_count;
1006     pjsip_dlg_dec_lock(dlg);
1007 
1008     pj_log_pop_indent();
1009     return PJ_SUCCESS;
1010 }
1011 
pjsip_dlg_get_lock(pjsip_dialog * dlg)1012 PJ_DEF(pj_grp_lock_t *) pjsip_dlg_get_lock(pjsip_dialog *dlg)
1013 {
1014     PJ_ASSERT_RETURN(dlg, NULL);
1015     return dlg->grp_lock_;
1016 }
1017 
1018 /*
1019  * Check if the module is registered as a usage
1020  */
pjsip_dlg_has_usage(pjsip_dialog * dlg,pjsip_module * mod)1021 PJ_DEF(pj_bool_t) pjsip_dlg_has_usage( pjsip_dialog *dlg,
1022 					  pjsip_module *mod)
1023 {
1024     unsigned index;
1025     pj_bool_t found = PJ_FALSE;
1026 
1027     pjsip_dlg_inc_lock(dlg);
1028     for (index=0; index<dlg->usage_cnt; ++index) {
1029     	if (dlg->usage[index] == mod) {
1030     	    found = PJ_TRUE;
1031     	    break;
1032     	}
1033     }
1034     pjsip_dlg_dec_lock(dlg);
1035 
1036     return found;
1037 }
1038 
1039 /*
1040  * Add usage.
1041  */
pjsip_dlg_add_usage(pjsip_dialog * dlg,pjsip_module * mod,void * mod_data)1042 PJ_DEF(pj_status_t) pjsip_dlg_add_usage( pjsip_dialog *dlg,
1043 					 pjsip_module *mod,
1044 					 void *mod_data )
1045 {
1046     unsigned index;
1047 
1048     PJ_ASSERT_RETURN(dlg && mod, PJ_EINVAL);
1049     PJ_ASSERT_RETURN(mod->id >= 0 && mod->id < PJSIP_MAX_MODULE,
1050 		     PJ_EINVAL);
1051     PJ_ASSERT_RETURN(dlg->usage_cnt < PJSIP_MAX_MODULE, PJ_EBUG);
1052 
1053     PJ_LOG(5,(dlg->obj_name,
1054 	      "Module %.*s added as dialog usage, data=%p",
1055 	      (int)mod->name.slen, mod->name.ptr, mod_data));
1056 
1057     pjsip_dlg_inc_lock(dlg);
1058 
1059     /* Usages are sorted on priority, lowest number first.
1060      * Find position to put the new module, also makes sure that
1061      * this module has not been registered before.
1062      */
1063     for (index=0; index<dlg->usage_cnt; ++index) {
1064 	if (dlg->usage[index] == mod) {
1065 	    /* Module may be registered more than once in the same dialog.
1066 	     * For example, when call transfer fails, application may retry
1067 	     * call transfer on the same dialog.
1068 	     * So return PJ_SUCCESS here.
1069 	     */
1070 	    PJ_LOG(4,(dlg->obj_name,
1071 		      "Module %.*s already registered as dialog usage, "
1072 		      "updating the data %p",
1073 		      (int)mod->name.slen, mod->name.ptr, mod_data));
1074 	    dlg->mod_data[mod->id] = mod_data;
1075 
1076 	    pjsip_dlg_dec_lock(dlg);
1077 	    return PJ_SUCCESS;
1078 
1079 	    //pj_assert(!"This module is already registered");
1080 	    //pjsip_dlg_dec_lock(dlg);
1081 	    //return PJSIP_ETYPEEXISTS;
1082 	}
1083 
1084 	if (dlg->usage[index]->priority > mod->priority)
1085 	    break;
1086     }
1087 
1088     /* index holds position to put the module.
1089      * Insert module at this index.
1090      */
1091     pj_array_insert(dlg->usage, sizeof(dlg->usage[0]), dlg->usage_cnt,
1092 		    index, &mod);
1093 
1094     /* Set module data. */
1095     dlg->mod_data[mod->id] = mod_data;
1096 
1097     /* Increment count. */
1098     ++dlg->usage_cnt;
1099 
1100     pjsip_dlg_dec_lock(dlg);
1101 
1102     return PJ_SUCCESS;
1103 }
1104 
1105 
1106 /*
1107  * Attach module specific data to the dialog. Application can also set
1108  * the value directly by accessing dlg->mod_data[module_id].
1109  */
pjsip_dlg_set_mod_data(pjsip_dialog * dlg,int mod_id,void * data)1110 PJ_DEF(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
1111 					    int mod_id,
1112 					    void *data )
1113 {
1114     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
1115     PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
1116 		     PJ_EINVAL);
1117     dlg->mod_data[mod_id] = data;
1118     return PJ_SUCCESS;
1119 }
1120 
1121 /**
1122  * Get module specific data previously attached to the dialog. Application
1123  * can also get value directly by accessing dlg->mod_data[module_id].
1124  */
pjsip_dlg_get_mod_data(pjsip_dialog * dlg,int mod_id)1125 PJ_DEF(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,
1126 				      int mod_id)
1127 {
1128     PJ_ASSERT_RETURN(dlg, NULL);
1129     PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
1130 		     NULL);
1131     return dlg->mod_data[mod_id];
1132 }
1133 
1134 
1135 /*
1136  * Create a new request within dialog (i.e. after the dialog session has been
1137  * established). The construction of such requests follows the rule in
1138  * RFC3261 section 12.2.1.
1139  */
dlg_create_request_throw(pjsip_dialog * dlg,const pjsip_method * method,int cseq,pjsip_tx_data ** p_tdata)1140 static pj_status_t dlg_create_request_throw( pjsip_dialog *dlg,
1141 					     const pjsip_method *method,
1142 					     int cseq,
1143 					     pjsip_tx_data **p_tdata )
1144 {
1145     pjsip_tx_data *tdata;
1146     pjsip_contact_hdr *contact;
1147     pjsip_route_hdr *route, *end_list;
1148     pj_status_t status;
1149 
1150     /* Contact Header field.
1151      * Contact can only be present in requests that establish dialog (in the
1152      * core SIP spec, only INVITE).
1153      */
1154     if (pjsip_method_creates_dialog(method))
1155 	contact = dlg->local.contact;
1156     else
1157 	contact = NULL;
1158 
1159     /*
1160      * Create the request by cloning from the headers in the
1161      * dialog.
1162      */
1163     status = pjsip_endpt_create_request_from_hdr(dlg->endpt,
1164 						 method,
1165 						 dlg->target,
1166 						 dlg->local.info,
1167 						 dlg->remote.info,
1168 						 contact,
1169 						 dlg->call_id,
1170 						 cseq,
1171 						 NULL,
1172 						 &tdata);
1173     if (status != PJ_SUCCESS)
1174 	return status;
1175 
1176     /* Put this dialog in tdata's mod_data */
1177     tdata->mod_data[dlg->ua->id] = dlg;
1178 
1179     /* Just copy dialog route-set to Route header.
1180      * The transaction will do the processing as specified in Section 12.2.1
1181      * of RFC 3261 in function tsx_process_route() in sip_transaction.c.
1182      */
1183     route = dlg->route_set.next;
1184     end_list = &dlg->route_set;
1185     for (; route != end_list; route = route->next ) {
1186 	pjsip_route_hdr *r;
1187 	r = (pjsip_route_hdr*) pjsip_hdr_shallow_clone( tdata->pool, route );
1188 	pjsip_routing_hdr_set_route(r);
1189 	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)r);
1190     }
1191 
1192     /* Copy authorization headers, if request is not ACK or CANCEL. */
1193     if (method->id != PJSIP_ACK_METHOD && method->id != PJSIP_CANCEL_METHOD) {
1194 	status = pjsip_auth_clt_init_req( &dlg->auth_sess, tdata );
1195 	if (status != PJ_SUCCESS)
1196 	    return status;
1197     }
1198 
1199     /* Copy the initial destination host to tdata. This information can be
1200      * used later by transport for transport selection.
1201      */
1202     if (dlg->initial_dest.slen)
1203     	pj_strdup(tdata->pool, &tdata->dest_info.name, &dlg->initial_dest);
1204 
1205     /* Done. */
1206     *p_tdata = tdata;
1207 
1208     return PJ_SUCCESS;
1209 }
1210 
1211 
1212 
1213 /*
1214  * Create outgoing request.
1215  */
pjsip_dlg_create_request(pjsip_dialog * dlg,const pjsip_method * method,int cseq,pjsip_tx_data ** p_tdata)1216 PJ_DEF(pj_status_t) pjsip_dlg_create_request( pjsip_dialog *dlg,
1217 					      const pjsip_method *method,
1218 					      int cseq,
1219 					      pjsip_tx_data **p_tdata)
1220 {
1221     pj_status_t status;
1222     pjsip_tx_data *tdata = NULL;
1223     PJ_USE_EXCEPTION;
1224 
1225     PJ_ASSERT_RETURN(dlg && method && p_tdata, PJ_EINVAL);
1226 
1227     /* Lock dialog. */
1228     pjsip_dlg_inc_lock(dlg);
1229 
1230     /* Use outgoing CSeq and increment it by one. */
1231     if (cseq < 0)
1232 	cseq = dlg->local.cseq + 1;
1233 
1234     /* Keep compiler happy */
1235     status = PJ_EBUG;
1236 
1237     /* Create the request. */
1238     PJ_TRY {
1239 	status = dlg_create_request_throw(dlg, method, cseq, &tdata);
1240     }
1241     PJ_CATCH_ANY {
1242 	status = PJ_ENOMEM;
1243     }
1244     PJ_END;
1245 
1246     /* Failed! Delete transmit data. */
1247     if (status != PJ_SUCCESS && tdata) {
1248 	pjsip_tx_data_dec_ref( tdata );
1249 	tdata = NULL;
1250     }
1251 
1252     /* Unlock dialog. */
1253     pjsip_dlg_dec_lock(dlg);
1254 
1255     *p_tdata = tdata;
1256 
1257     return status;
1258 }
1259 
1260 /* Callback for send ACK, providing send callback will allow stack to try
1261  * next server upon failure.
1262  */
send_ack_callback(pjsip_send_state * send_state,pj_ssize_t sent,pj_bool_t * cont)1263 static void send_ack_callback( pjsip_send_state *send_state,
1264 			       pj_ssize_t sent, pj_bool_t *cont )
1265 {
1266     if (sent > 0)
1267 	return;
1268 
1269     if (*cont) {
1270 	PJ_PERROR(3,(THIS_FILE, (pj_status_t)-sent,
1271 		     "Temporary failure in sending %s, "
1272 		     "will try next server",
1273 		     pjsip_tx_data_get_info(send_state->tdata)));
1274     } else {
1275 	PJ_PERROR(3,(THIS_FILE, (pj_status_t)-sent,
1276 		     "Failed to send %s!",
1277 		     pjsip_tx_data_get_info(send_state->tdata)));
1278     }
1279 }
1280 
1281 /*
1282  * Send request statefully, and update dialog'c CSeq.
1283  */
pjsip_dlg_send_request(pjsip_dialog * dlg,pjsip_tx_data * tdata,int mod_data_id,void * mod_data)1284 PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,
1285 					    pjsip_tx_data *tdata,
1286 					    int mod_data_id,
1287 					    void *mod_data)
1288 {
1289     pjsip_transaction *tsx;
1290     pjsip_msg *msg = tdata->msg;
1291     pj_status_t status;
1292 
1293     /* Check arguments. */
1294     PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
1295     PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
1296 		     PJSIP_ENOTREQUESTMSG);
1297 
1298     pj_log_push_indent();
1299     PJ_LOG(5,(dlg->obj_name, "Sending %s",
1300 	      pjsip_tx_data_get_info(tdata)));
1301 
1302     /* Lock and increment session */
1303     pjsip_dlg_inc_lock(dlg);
1304 
1305     /* Put this dialog in tdata's mod_data */
1306     tdata->mod_data[dlg->ua->id] = dlg;
1307 
1308     /* If via_addr is set, use this address for the Via header. */
1309     if (dlg->via_addr.host.slen > 0) {
1310         tdata->via_addr = dlg->via_addr;
1311         tdata->via_tp = dlg->via_tp;
1312     }
1313 
1314     /* Update dialog's CSeq and message's CSeq if request is not
1315      * ACK nor CANCEL.
1316      */
1317     if (msg->line.req.method.id != PJSIP_CANCEL_METHOD &&
1318 	msg->line.req.method.id != PJSIP_ACK_METHOD)
1319     {
1320 	pjsip_cseq_hdr *ch;
1321 
1322 	ch = PJSIP_MSG_CSEQ_HDR(msg);
1323 	PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG);
1324 
1325 	ch->cseq = dlg->local.cseq++;
1326 
1327 	/* Force the whole message to be re-printed. */
1328 	pjsip_tx_data_invalidate_msg( tdata );
1329     }
1330 
1331     /* Create a new transaction if method is not ACK.
1332      * The transaction user is the user agent module.
1333      */
1334     if (msg->line.req.method.id != PJSIP_ACK_METHOD) {
1335 	int tsx_count;
1336 
1337 	status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);
1338 	if (status != PJ_SUCCESS)
1339 	    goto on_error;
1340 
1341 	/* Set transport selector */
1342 	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
1343 	pj_assert(status == PJ_SUCCESS);
1344 
1345 	/* Attach this dialog to the transaction, so that user agent
1346 	 * will dispatch events to this dialog.
1347 	 */
1348 	tsx->mod_data[dlg->ua->id] = dlg;
1349 
1350 	/* Copy optional caller's mod_data, if present */
1351 	if (mod_data_id >= 0 && mod_data_id < PJSIP_MAX_MODULE)
1352 	    tsx->mod_data[mod_data_id] = mod_data;
1353 
1354 	/* Increment transaction counter. */
1355 	tsx_count = ++dlg->tsx_count;
1356 
1357 	/* Send the message. */
1358 	status = pjsip_tsx_send_msg(tsx, tdata);
1359 	if (status != PJ_SUCCESS) {
1360 	    if (dlg->tsx_count == tsx_count)
1361 		pjsip_tsx_terminate(tsx, tsx->status_code);
1362 	    goto on_error;
1363 	}
1364 
1365     } else {
1366 	/* Set transport selector */
1367 	pjsip_tx_data_set_transport(tdata, &dlg->tp_sel);
1368 
1369 	/* Send request */
1370 	status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata,
1371 						    NULL, &send_ack_callback);
1372 	if (status != PJ_SUCCESS)
1373 	    goto on_error;
1374 
1375     }
1376 
1377     /* Unlock dialog, may destroy dialog. */
1378     pjsip_dlg_dec_lock(dlg);
1379     pj_log_pop_indent();
1380     return PJ_SUCCESS;
1381 
1382 on_error:
1383     /* Unlock dialog, may destroy dialog. */
1384     pjsip_dlg_dec_lock(dlg);
1385 
1386     /* Whatever happen delete the message. */
1387     pjsip_tx_data_dec_ref( tdata );
1388     pj_log_pop_indent();
1389     return status;
1390 }
1391 
1392 /* Add standard headers for certain types of response */
dlg_beautify_response(pjsip_dialog * dlg,pj_bool_t add_headers,int st_code,pjsip_tx_data * tdata)1393 static void dlg_beautify_response(pjsip_dialog *dlg,
1394 				  pj_bool_t add_headers,
1395 				  int st_code,
1396 				  pjsip_tx_data *tdata)
1397 {
1398     pjsip_cseq_hdr *cseq;
1399     int st_class;
1400     const pjsip_hdr *c_hdr;
1401     pjsip_hdr *hdr;
1402 
1403     cseq = PJSIP_MSG_CSEQ_HDR(tdata->msg);
1404     pj_assert(cseq != NULL);
1405 
1406     st_class = st_code / 100;
1407 
1408     /* Contact, Allow, Supported header. */
1409     if (add_headers && pjsip_method_creates_dialog(&cseq->method)) {
1410 	/* Add Contact header for 1xx, 2xx, 3xx and 485 response. */
1411 	if (st_class==2 || st_class==3 || (st_class==1 && st_code != 100) ||
1412 	    st_code==485)
1413 	{
1414 	    /* Add contact header only if one is not present. */
1415 	    if (pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL) == 0 &&
1416 		pjsip_msg_find_hdr_by_name(tdata->msg, &HCONTACT, NULL) == 0)
1417 	    {
1418 		hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool,
1419 						   dlg->local.contact);
1420 		pjsip_msg_add_hdr(tdata->msg, hdr);
1421 	    }
1422 	}
1423 
1424 	/* Add Allow header in 18x, 2xx and 405 response. */
1425 	if ((((st_code/10==18 || st_class==2) && dlg->add_allow)
1426 	     || st_code==405) &&
1427 	    pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ALLOW, NULL)==NULL)
1428 	{
1429 	    c_hdr = pjsip_endpt_get_capability(dlg->endpt,
1430 					       PJSIP_H_ALLOW, NULL);
1431 	    if (c_hdr) {
1432 		hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, c_hdr);
1433 		pjsip_msg_add_hdr(tdata->msg, hdr);
1434 	    }
1435 	}
1436 
1437 	/* Add Supported header in 2xx response. */
1438 	if (st_class==2 &&
1439 	    pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL)==NULL)
1440 	{
1441 	    c_hdr = pjsip_endpt_get_capability(dlg->endpt,
1442 					       PJSIP_H_SUPPORTED, NULL);
1443 	    if (c_hdr) {
1444 		hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, c_hdr);
1445 		pjsip_msg_add_hdr(tdata->msg, hdr);
1446 	    }
1447 	}
1448 
1449     }
1450 
1451     /* Add To tag in all responses except 100 */
1452     if (st_code != 100) {
1453 	pjsip_to_hdr *to;
1454 
1455 	to = PJSIP_MSG_TO_HDR(tdata->msg);
1456 	pj_assert(to != NULL);
1457 
1458 	to->tag = dlg->local.info->tag;
1459 
1460 	if (dlg->state == PJSIP_DIALOG_STATE_NULL)
1461 	    dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED;
1462     }
1463 }
1464 
1465 
1466 /*
1467  * Create response.
1468  */
pjsip_dlg_create_response(pjsip_dialog * dlg,pjsip_rx_data * rdata,int st_code,const pj_str_t * st_text,pjsip_tx_data ** p_tdata)1469 PJ_DEF(pj_status_t) pjsip_dlg_create_response(	pjsip_dialog *dlg,
1470 						pjsip_rx_data *rdata,
1471 						int st_code,
1472 						const pj_str_t *st_text,
1473 						pjsip_tx_data **p_tdata)
1474 {
1475     pj_status_t status;
1476     pjsip_tx_data *tdata;
1477 
1478     /* Create generic response.
1479      * This will initialize response's Via, To, From, Call-ID, CSeq
1480      * and Record-Route headers from the request.
1481      */
1482     status = pjsip_endpt_create_response(dlg->endpt,
1483 					 rdata, st_code, st_text, &tdata);
1484     if (status != PJ_SUCCESS)
1485 	return status;
1486 
1487     /* Lock the dialog. */
1488     pjsip_dlg_inc_lock(dlg);
1489 
1490     /* Put this dialog in tdata's mod_data */
1491     tdata->mod_data[dlg->ua->id] = dlg;
1492 
1493     dlg_beautify_response(dlg, PJ_FALSE, st_code, tdata);
1494 
1495     /* Unlock the dialog. */
1496     pjsip_dlg_dec_lock(dlg);
1497 
1498     /* Done. */
1499     *p_tdata = tdata;
1500     return PJ_SUCCESS;
1501 }
1502 
1503 /*
1504  * Modify response.
1505  */
pjsip_dlg_modify_response(pjsip_dialog * dlg,pjsip_tx_data * tdata,int st_code,const pj_str_t * st_text)1506 PJ_DEF(pj_status_t) pjsip_dlg_modify_response(	pjsip_dialog *dlg,
1507 						pjsip_tx_data *tdata,
1508 						int st_code,
1509 						const pj_str_t *st_text)
1510 {
1511     pjsip_hdr *hdr;
1512 
1513     PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
1514     PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
1515 		     PJSIP_ENOTRESPONSEMSG);
1516     PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL);
1517 
1518     /* Lock and increment session */
1519     pjsip_dlg_inc_lock(dlg);
1520 
1521     /* Replace status code and reason */
1522     tdata->msg->line.status.code = st_code;
1523     if (st_text) {
1524 	pj_strdup(tdata->pool, &tdata->msg->line.status.reason, st_text);
1525     } else {
1526 	tdata->msg->line.status.reason = *pjsip_get_status_text(st_code);
1527     }
1528 
1529     /* Remove existing Contact header (without this, when dialog sent
1530      * 180 and then 302, the Contact in 302 will not get updated).
1531      */
1532     hdr = (pjsip_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
1533     if (hdr)
1534 	pj_list_erase(hdr);
1535 
1536     /* Add tag etc. if necessary */
1537     dlg_beautify_response(dlg, st_code/100 <= 2, st_code, tdata);
1538 
1539 
1540     /* Must add reference counter, since tsx_send_msg() will decrement it */
1541     pjsip_tx_data_add_ref(tdata);
1542 
1543     /* Force to re-print message. */
1544     pjsip_tx_data_invalidate_msg(tdata);
1545 
1546     /* Unlock dialog and dec session, may destroy dialog. */
1547     pjsip_dlg_dec_lock(dlg);
1548 
1549     return PJ_SUCCESS;
1550 }
1551 
1552 /*
1553  * Send response statefully.
1554  */
pjsip_dlg_send_response(pjsip_dialog * dlg,pjsip_transaction * tsx,pjsip_tx_data * tdata)1555 PJ_DEF(pj_status_t) pjsip_dlg_send_response( pjsip_dialog *dlg,
1556 					     pjsip_transaction *tsx,
1557 					     pjsip_tx_data *tdata)
1558 {
1559     pj_status_t status;
1560 
1561     /* Sanity check. */
1562     PJ_ASSERT_RETURN(dlg && tsx && tdata && tdata->msg, PJ_EINVAL);
1563     PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_RESPONSE_MSG,
1564 		     PJSIP_ENOTRESPONSEMSG);
1565 
1566     /* The transaction must belong to this dialog.  */
1567     PJ_ASSERT_RETURN(tsx->mod_data[dlg->ua->id] == dlg, PJ_EINVALIDOP);
1568 
1569     pj_log_push_indent();
1570 
1571     PJ_LOG(5,(dlg->obj_name, "Sending %s",
1572 	      pjsip_tx_data_get_info(tdata)));
1573 
1574     /* Check that transaction method and cseq match the response.
1575      * This operation is sloooww (search CSeq header twice), that's why
1576      * we only do it in debug mode.
1577      */
1578 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
1579     PJ_ASSERT_RETURN( PJSIP_MSG_CSEQ_HDR(tdata->msg)->cseq == tsx->cseq &&
1580 		      pjsip_method_cmp(&PJSIP_MSG_CSEQ_HDR(tdata->msg)->method,
1581 				       &tsx->method)==0,
1582 		      PJ_EINVALIDOP);
1583 #endif
1584 
1585     /* Must acquire dialog first, to prevent deadlock */
1586     pjsip_dlg_inc_lock(dlg);
1587 
1588     /* Last chance to add mandatory headers before the response is
1589      * sent.
1590      */
1591     dlg_beautify_response(dlg, PJ_TRUE, tdata->msg->line.status.code, tdata);
1592 
1593     /* If the dialog is locked to transport, make sure that transaction
1594      * is locked to the same transport too.
1595      */
1596     if (dlg->tp_sel.type != tsx->tp_sel.type ||
1597 	dlg->tp_sel.u.ptr != tsx->tp_sel.u.ptr)
1598     {
1599 	status = pjsip_tsx_set_transport(tsx, &dlg->tp_sel);
1600 	pj_assert(status == PJ_SUCCESS);
1601     }
1602 
1603     /* Ask transaction to send the response */
1604     status = pjsip_tsx_send_msg(tsx, tdata);
1605 
1606     /* This function must decrement transmit data request counter
1607      * regardless of the operation status. The transaction only
1608      * decrements the counter if the operation is successful.
1609      */
1610     if (status != PJ_SUCCESS) {
1611 	pjsip_tx_data_dec_ref(tdata);
1612     }
1613 
1614     pjsip_dlg_dec_lock(dlg);
1615     pj_log_pop_indent();
1616 
1617     return status;
1618 }
1619 
1620 
1621 /*
1622  * Combo function to create and send response statefully.
1623  */
pjsip_dlg_respond(pjsip_dialog * dlg,pjsip_rx_data * rdata,int st_code,const pj_str_t * st_text,const pjsip_hdr * hdr_list,const pjsip_msg_body * body)1624 PJ_DEF(pj_status_t) pjsip_dlg_respond(  pjsip_dialog *dlg,
1625 					pjsip_rx_data *rdata,
1626 					int st_code,
1627 					const pj_str_t *st_text,
1628 					const pjsip_hdr *hdr_list,
1629 					const pjsip_msg_body *body )
1630 {
1631     pj_status_t status;
1632     pjsip_tx_data *tdata;
1633 
1634     /* Sanity check. */
1635     PJ_ASSERT_RETURN(dlg && rdata && rdata->msg_info.msg, PJ_EINVAL);
1636     PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
1637 		     PJSIP_ENOTREQUESTMSG);
1638 
1639     /* The transaction must belong to this dialog.  */
1640     PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata) &&
1641 		     pjsip_rdata_get_tsx(rdata)->mod_data[dlg->ua->id] == dlg,
1642 		     PJ_EINVALIDOP);
1643 
1644     /* Create the response. */
1645     status = pjsip_dlg_create_response(dlg, rdata, st_code, st_text, &tdata);
1646     if (status != PJ_SUCCESS)
1647 	return status;
1648 
1649     /* Add additional header, if any */
1650     if (hdr_list) {
1651 	const pjsip_hdr *hdr;
1652 
1653 	hdr = hdr_list->next;
1654 	while (hdr != hdr_list) {
1655 	    pjsip_msg_add_hdr(tdata->msg,
1656 			      (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
1657 	    hdr = hdr->next;
1658 	}
1659     }
1660 
1661     /* Add the message body, if any. */
1662     if (body) {
1663 	tdata->msg->body = pjsip_msg_body_clone( tdata->pool, body);
1664     }
1665 
1666     /* Send the response. */
1667     return pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
1668 }
1669 
1670 
1671 /* This function is called by user agent upon receiving incoming request
1672  * message.
1673  */
pjsip_dlg_on_rx_request(pjsip_dialog * dlg,pjsip_rx_data * rdata)1674 void pjsip_dlg_on_rx_request( pjsip_dialog *dlg, pjsip_rx_data *rdata )
1675 {
1676     pj_status_t status;
1677     pjsip_transaction *tsx = NULL;
1678     pj_bool_t processed = PJ_FALSE;
1679     unsigned i;
1680 
1681     PJ_LOG(5,(dlg->obj_name, "Received %s",
1682 	      pjsip_rx_data_get_info(rdata)));
1683     pj_log_push_indent();
1684 
1685     /* Lock dialog and increment session. */
1686     pjsip_dlg_inc_lock(dlg);
1687 
1688     /* Check CSeq */
1689     if (rdata->msg_info.cseq->cseq <= dlg->remote.cseq &&
1690 	rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD &&
1691 	rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD)
1692     {
1693 	/* Invalid CSeq.
1694 	 * Respond statelessly with 500 (Internal Server Error)
1695 	 */
1696 	pj_str_t warn_text;
1697 
1698 	/* Unlock dialog and dec session, may destroy dialog. */
1699 	pjsip_dlg_dec_lock(dlg);
1700 
1701 	pj_assert(pjsip_rdata_get_tsx(rdata) == NULL);
1702 	warn_text = pj_str("Invalid CSeq");
1703 	pjsip_endpt_respond_stateless(dlg->endpt,
1704 				      rdata, 500, &warn_text, NULL, NULL);
1705 	pj_log_pop_indent();
1706 	return;
1707     }
1708 
1709     /* Update CSeq. */
1710     dlg->remote.cseq = rdata->msg_info.cseq->cseq;
1711 
1712     /* Update To tag if necessary.
1713      * This only happens if UAS sends a new request before answering
1714      * our request (e.g. UAS sends NOTIFY before answering our
1715      * SUBSCRIBE request).
1716      */
1717     if (dlg->remote.info->tag.slen == 0) {
1718 	pj_strdup(dlg->pool, &dlg->remote.info->tag,
1719 		  &rdata->msg_info.from->tag);
1720     }
1721 
1722     /* Create UAS transaction for this request. */
1723     if (pjsip_rdata_get_tsx(rdata) == NULL &&
1724 	rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD)
1725     {
1726 	status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx);
1727 	if (status != PJ_SUCCESS) {
1728 	    /* Once case for this is when re-INVITE contains same
1729 	     * Via branch value as previous INVITE (ticket #965).
1730 	     */
1731 	    char errmsg[PJ_ERR_MSG_SIZE];
1732 	    pj_str_t reason;
1733 
1734 	    reason = pj_strerror(status, errmsg, sizeof(errmsg));
1735 	    pjsip_endpt_respond_stateless(dlg->endpt, rdata, 500, &reason,
1736 					  NULL, NULL);
1737 	    goto on_return;
1738 	}
1739 
1740 	/* Put this dialog in the transaction data. */
1741 	tsx->mod_data[dlg->ua->id] = dlg;
1742 
1743 	/* Add transaction count. */
1744 	++dlg->tsx_count;
1745     }
1746 
1747     /* Update the target URI if this is a target refresh request.
1748      * We have passed the basic checking for the request, I think we
1749      * should update the target URI regardless of whether the request
1750      * is accepted or not (e.g. when re-INVITE is answered with 488,
1751      * we would still need to update the target URI, otherwise our
1752      * target URI would be wrong, wouldn't it).
1753      */
1754     if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method)) {
1755 	pjsip_contact_hdr *contact;
1756 
1757 	contact = (pjsip_contact_hdr*)
1758 		  pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
1759 				     NULL);
1760 	if (contact && contact->uri &&
1761 	    (dlg->remote.contact==NULL ||
1762  	     pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
1763 			   dlg->remote.contact->uri,
1764 			   contact->uri)))
1765 	{
1766 	    dlg->remote.contact = (pjsip_contact_hdr*)
1767 	    			  pjsip_hdr_clone(dlg->pool, contact);
1768 	    dlg->target = dlg->remote.contact->uri;
1769 	}
1770     }
1771 
1772     /* Report the request to dialog usages. */
1773     for (i=0; i<dlg->usage_cnt; ++i) {
1774 
1775 	if (!dlg->usage[i]->on_rx_request)
1776 	    continue;
1777 
1778 	processed = (*dlg->usage[i]->on_rx_request)(rdata);
1779 
1780 	if (processed)
1781 	    break;
1782     }
1783 
1784     /* Feed the first request to the transaction. */
1785     if (tsx)
1786 	pjsip_tsx_recv_msg(tsx, rdata);
1787 
1788     /* If no dialog usages has claimed the processing of the transaction,
1789      * and if transaction has not sent final response, respond with
1790      * 500/Internal Server Error.
1791      */
1792     if (!processed && tsx && tsx->status_code < 200) {
1793 	pjsip_tx_data *tdata;
1794 	const pj_str_t reason = { "Unhandled by dialog usages", 26};
1795 
1796 	PJ_LOG(4,(tsx->obj_name, "%s was unhandled by "
1797 				 "dialog usages, sending 500 response",
1798 				 pjsip_rx_data_get_info(rdata)));
1799 
1800 	status = pjsip_dlg_create_response(dlg, rdata, 500, &reason, &tdata);
1801 	if (status == PJ_SUCCESS) {
1802 	    status = pjsip_dlg_send_response(dlg, tsx, tdata);
1803 	}
1804     }
1805 
1806 on_return:
1807     /* Unlock dialog and dec session, may destroy dialog. */
1808     pjsip_dlg_dec_lock(dlg);
1809     pj_log_pop_indent();
1810 }
1811 
1812 /* Update route-set from incoming message */
dlg_update_routeset(pjsip_dialog * dlg,const pjsip_rx_data * rdata)1813 static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_rx_data *rdata)
1814 {
1815     const pjsip_hdr *hdr, *end_hdr;
1816     //pj_int32_t msg_cseq;
1817     const pjsip_msg *msg;
1818     const pjsip_method update = { PJSIP_OTHER_METHOD, {"UPDATE", 6}};
1819 
1820     msg = rdata->msg_info.msg;
1821     //msg_cseq = rdata->msg_info.cseq->cseq;
1822 
1823     /* Ignore if route set has been frozen */
1824     if (dlg->route_set_frozen)
1825 	return;
1826 
1827     /* Ignore if the message is an UPDATE response (see ticket #1781) */
1828     if (pjsip_method_cmp(&rdata->msg_info.cseq->method, &update) == 0)
1829 	return;
1830 
1831     /* Only update route set if this message belongs to the same
1832      * transaction as the initial transaction that establishes dialog.
1833      */
1834     if (dlg->role == PJSIP_ROLE_UAC) {
1835     	/* Save initial destination host from transport's info. */
1836     	if (!dlg->initial_dest.slen) {
1837     	    pj_strdup(dlg->pool, &dlg->initial_dest,
1838     	      	      &rdata->tp_info.transport->remote_name.host);
1839     	}
1840 
1841 	/* Ignore subsequent request from remote */
1842 	if (msg->type != PJSIP_RESPONSE_MSG)
1843 	    return;
1844 
1845 	/* Ignore subsequent responses with higher CSeq than initial CSeq.
1846 	 * Unfortunately this would be broken when the first request is
1847 	 * challenged!
1848 	 */
1849 	//if (msg_cseq != dlg->local.first_cseq)
1850 	//    return;
1851 
1852     } else {
1853 
1854 	/* For callee dialog, route set should have been set by initial
1855 	 * request and it will have been rejected by dlg->route_set_frozen
1856 	 * check above.
1857 	 */
1858 	pj_assert(!"Should not happen");
1859 
1860     }
1861 
1862     /* Based on the checks above, we should only get response message here */
1863     pj_assert(msg->type == PJSIP_RESPONSE_MSG);
1864 
1865     /* Ignore if this is not 1xx or 2xx response */
1866     if (msg->line.status.code >= 300)
1867 	return;
1868 
1869     /* Reset route set */
1870     pj_list_init(&dlg->route_set);
1871 
1872     /* Update route set */
1873     end_hdr = &msg->hdr;
1874     for (hdr=msg->hdr.prev; hdr!=end_hdr; hdr=hdr->prev) {
1875 	if (hdr->type == PJSIP_H_RECORD_ROUTE) {
1876 	    pjsip_route_hdr *r;
1877 	    r = (pjsip_route_hdr*) pjsip_hdr_clone(dlg->pool, hdr);
1878 	    pjsip_routing_hdr_set_route(r);
1879 	    pj_list_push_back(&dlg->route_set, r);
1880 	}
1881     }
1882 
1883     PJ_LOG(5,(dlg->obj_name, "Route-set updated"));
1884 
1885     /* Freeze the route set only when the route set comes in 2xx response.
1886      * If it is in 1xx response, prepare to recompute the route set when
1887      * the 2xx response comes in.
1888      *
1889      * There is a debate whether route set should be frozen when the dialog
1890      * is established with reliable provisional response, but I think
1891      * it is safer to not freeze the route set (thus recompute the route set
1892      * upon receiving 2xx response). Also RFC 3261 says so in 13.2.2.4.
1893      *
1894      * The pjsip_method_creates_dialog() check protects from wrongly
1895      * freezing the route set upon receiving 200/OK response for PRACK.
1896      */
1897     if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) &&
1898 	PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200))
1899     {
1900 	dlg->route_set_frozen = PJ_TRUE;
1901 	PJ_LOG(5,(dlg->obj_name, "Route-set frozen"));
1902     }
1903 }
1904 
1905 
1906 /* This function is called by user agent upon receiving incoming response
1907  * message.
1908  */
pjsip_dlg_on_rx_response(pjsip_dialog * dlg,pjsip_rx_data * rdata)1909 void pjsip_dlg_on_rx_response( pjsip_dialog *dlg, pjsip_rx_data *rdata )
1910 {
1911     unsigned i;
1912     int res_code;
1913 
1914     PJ_LOG(5,(dlg->obj_name, "Received %s",
1915 	      pjsip_rx_data_get_info(rdata)));
1916     pj_log_push_indent();
1917 
1918     /* Lock the dialog and inc session. */
1919     pjsip_dlg_inc_lock(dlg);
1920 
1921     /* Check that rdata already has dialog in mod_data. */
1922     pj_assert(pjsip_rdata_get_dlg(rdata) == dlg);
1923 
1924     /* Keep the response's status code */
1925     res_code = rdata->msg_info.msg->line.status.code;
1926 
1927     /* When we receive response that establishes dialog, update To tag,
1928      * route set and dialog target.
1929      *
1930      * The second condition of the "if" is a workaround for forking.
1931      * Originally, the dialog takes the first To tag seen and set it as
1932      * the remote tag. If the tag in 2xx response is different than this
1933      * tag, ACK will be sent with wrong To tag and incoming request with
1934      * this tag will be rejected with 481.
1935      *
1936      * The workaround for this is to take the To tag received in the
1937      * 2xx response and set it as remote tag.
1938      *
1939      * New update:
1940      * We also need to update the dialog for 1xx responses, to handle the
1941      * case when 100rel is used, otherwise PRACK will be sent to the
1942      * wrong target.
1943      */
1944     if ((dlg->state == PJSIP_DIALOG_STATE_NULL &&
1945 	 pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) &&
1946 	 (res_code > 100 && res_code < 300) &&
1947 	 rdata->msg_info.to->tag.slen)
1948 	 ||
1949 	(dlg->role==PJSIP_ROLE_UAC &&
1950 	 !dlg->uac_has_2xx &&
1951 	 res_code > 100 &&
1952 	 res_code/100 <= 2 &&
1953 	 pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) &&
1954 	 pj_stricmp(&dlg->remote.info->tag, &rdata->msg_info.to->tag)))
1955     {
1956 	pjsip_contact_hdr *contact;
1957 
1958 	/* Update remote capability info, when To tags in the dialog remote
1959 	 * info and the incoming response are different, e.g: first response
1960 	 * with To-tag or forking, apply strict update.
1961 	 */
1962 	pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg,
1963 				    pj_stricmp(&dlg->remote.info->tag,
1964 					      &rdata->msg_info.to->tag));
1965 
1966 	/* Update To tag. */
1967 	pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag);
1968 	/* No need to update remote's tag_hval since its never used. */
1969 
1970 	/* RFC 3271 Section 12.1.2:
1971 	 * The route set MUST be set to the list of URIs in the Record-Route
1972 	 * header field from the response, taken in reverse order and
1973 	 * preserving all URI parameters. If no Record-Route header field
1974 	 * is present in the response, the route set MUST be set to the
1975 	 * empty set. This route set, even if empty, overrides any pre-existing
1976 	 * route set for future requests in this dialog.
1977 	 */
1978 	dlg_update_routeset(dlg, rdata);
1979 
1980 	/* The remote target MUST be set to the URI from the Contact header
1981 	 * field of the response.
1982 	 */
1983 	contact = (pjsip_contact_hdr*)
1984 		  pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
1985 				     NULL);
1986 	if (contact && contact->uri &&
1987 	    (dlg->remote.contact==NULL ||
1988 	     pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
1989 			   dlg->remote.contact->uri,
1990 			   contact->uri)))
1991 	{
1992 	    dlg->remote.contact = (pjsip_contact_hdr*)
1993 	    			  pjsip_hdr_clone(dlg->pool, contact);
1994 	    dlg->target = dlg->remote.contact->uri;
1995 	}
1996 
1997 	dlg->state = PJSIP_DIALOG_STATE_ESTABLISHED;
1998 
1999 	/* Prevent dialog from being updated just in case more 2xx
2000 	 * gets through this dialog (it shouldn't happen).
2001 	 */
2002 	if (dlg->role==PJSIP_ROLE_UAC && !dlg->uac_has_2xx &&
2003 	    res_code/100==2)
2004 	{
2005 	    dlg->uac_has_2xx = PJ_TRUE;
2006 	}
2007     }
2008 
2009     /* Update remote target (again) when receiving 2xx response messages
2010      * that's defined as target refresh.
2011      *
2012      * Also upon receiving 2xx response, recheck again the route set.
2013      * This is for compatibility with RFC 2543, as described in Section
2014      * 13.2.2.4 of RFC 3261:
2015 
2016 	If the dialog identifier in the 2xx response matches the dialog
2017 	identifier of an existing dialog, the dialog MUST be transitioned to
2018 	the "confirmed" state, and the route set for the dialog MUST be
2019 	recomputed based on the 2xx response using the procedures of Section
2020 	12.2.1.2.
2021 
2022 	Note that the only piece of state that is recomputed is the route
2023 	set.  Other pieces of state such as the highest sequence numbers
2024 	(remote and local) sent within the dialog are not recomputed.  The
2025 	route set only is recomputed for backwards compatibility.  RFC
2026 	2543 did not mandate mirroring of the Record-Route header field in
2027 	a 1xx, only 2xx.
2028      */
2029     if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) &&
2030 	res_code/100 == 2)
2031     {
2032 	pjsip_contact_hdr *contact;
2033 
2034 	contact = (pjsip_contact_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg,
2035 							  PJSIP_H_CONTACT,
2036 				     			  NULL);
2037 	if (contact && contact->uri &&
2038 	    (dlg->remote.contact==NULL ||
2039 	     pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI,
2040 			   dlg->remote.contact->uri,
2041 			   contact->uri)))
2042 	{
2043 	    dlg->remote.contact = (pjsip_contact_hdr*)
2044 	    			  pjsip_hdr_clone(dlg->pool, contact);
2045 	    dlg->target = dlg->remote.contact->uri;
2046 	}
2047 
2048 	dlg_update_routeset(dlg, rdata);
2049 
2050 	/* Update remote capability info after the first 2xx response
2051 	 * (ticket #1539). Note that the remote capability retrieved here
2052 	 * will be assumed to remain unchanged for the duration of the dialog.
2053 	 */
2054 	if (dlg->role==PJSIP_ROLE_UAC && !dlg->uac_has_2xx) {
2055 	    pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, PJ_FALSE);
2056 	    dlg->uac_has_2xx = PJ_TRUE;
2057 	}
2058     }
2059 
2060     /* Pass to dialog usages. */
2061     for (i=0; i<dlg->usage_cnt; ++i) {
2062 	pj_bool_t processed;
2063 
2064 	if (!dlg->usage[i]->on_rx_response)
2065 	    continue;
2066 
2067 	processed = (*dlg->usage[i]->on_rx_response)(rdata);
2068 
2069 	if (processed)
2070 	    break;
2071     }
2072 
2073     /* Handle the case of forked response, when the application creates
2074      * the forked dialog but not the invite session. In this case, the
2075      * forked 200/OK response will be unhandled, and we must send ACK
2076      * here.
2077      */
2078     if (dlg->usage_cnt==0) {
2079 	pj_status_t status;
2080 
2081 	if (rdata->msg_info.cseq->method.id==PJSIP_INVITE_METHOD &&
2082 	    rdata->msg_info.msg->line.status.code/100 == 2)
2083 	{
2084 	    pjsip_tx_data *ack;
2085 
2086 	    status = pjsip_dlg_create_request(dlg, &pjsip_ack_method,
2087 					      rdata->msg_info.cseq->cseq,
2088 					      &ack);
2089 	    if (status == PJ_SUCCESS)
2090 		status = pjsip_dlg_send_request(dlg, ack, -1, NULL);
2091 	} else if (rdata->msg_info.msg->line.status.code==401 ||
2092 		   rdata->msg_info.msg->line.status.code==407)
2093 	{
2094 	    pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
2095 	    pjsip_tx_data *tdata;
2096 
2097 	    status = pjsip_auth_clt_reinit_req( &dlg->auth_sess,
2098 						rdata, tsx->last_tx,
2099 						&tdata);
2100 
2101 	    if (status == PJ_SUCCESS) {
2102 		/* Re-send request. */
2103 		status = pjsip_dlg_send_request(dlg, tdata, -1, NULL);
2104 	    }
2105 	}
2106     }
2107 
2108     /* Unhandled response does not necessarily mean error because
2109        dialog usages may choose to process the transaction state instead.
2110     if (i==dlg->usage_cnt) {
2111 	PJ_LOG(4,(dlg->obj_name, "%s was not claimed by any dialog usages",
2112 		  pjsip_rx_data_get_info(rdata)));
2113     }
2114     */
2115 
2116     /* Unlock dialog and dec session, may destroy dialog. */
2117     pjsip_dlg_dec_lock(dlg);
2118 
2119     pj_log_pop_indent();
2120 }
2121 
2122 /* This function is called by user agent upon receiving transaction
2123  * state notification.
2124  */
pjsip_dlg_on_tsx_state(pjsip_dialog * dlg,pjsip_transaction * tsx,pjsip_event * e)2125 void pjsip_dlg_on_tsx_state( pjsip_dialog *dlg,
2126 			     pjsip_transaction *tsx,
2127 			     pjsip_event *e )
2128 {
2129     unsigned i;
2130 
2131     PJ_LOG(5,(dlg->obj_name, "Transaction %s state changed to %s",
2132 	      tsx->obj_name, pjsip_tsx_state_str(tsx->state)));
2133     pj_log_push_indent();
2134 
2135     /* Lock the dialog and increment session. */
2136     pjsip_dlg_inc_lock(dlg);
2137 
2138     /* Pass to dialog usages. */
2139     for (i=0; i<dlg->usage_cnt; ++i) {
2140 
2141 	if (!dlg->usage[i]->on_tsx_state)
2142 	    continue;
2143 
2144 	(*dlg->usage[i]->on_tsx_state)(tsx, e);
2145     }
2146 
2147 
2148     /* It is possible that the transaction is terminated and this function
2149      * is called while we're calling on_tsx_state(). So only decrement
2150      * the tsx_count if we're still attached to the transaction.
2151      */
2152     if (tsx->state == PJSIP_TSX_STATE_TERMINATED &&
2153 	tsx->mod_data[dlg->ua->id] == dlg)
2154     {
2155 	pj_assert(dlg->tsx_count>0);
2156 	--dlg->tsx_count;
2157 	tsx->mod_data[dlg->ua->id] = NULL;
2158     }
2159 
2160     /* Unlock dialog and dec session, may destroy dialog. */
2161     pjsip_dlg_dec_lock(dlg);
2162     pj_log_pop_indent();
2163 }
2164 
2165 
2166 /*
2167  * Check if the specified capability is supported by remote.
2168  */
pjsip_dlg_remote_has_cap(pjsip_dialog * dlg,int htype,const pj_str_t * hname,const pj_str_t * token)2169 PJ_DEF(pjsip_dialog_cap_status) pjsip_dlg_remote_has_cap(
2170 						    pjsip_dialog *dlg,
2171 						    int htype,
2172 						    const pj_str_t *hname,
2173 						    const pj_str_t *token)
2174 {
2175     const pjsip_generic_array_hdr *hdr;
2176     pjsip_dialog_cap_status cap_status = PJSIP_DIALOG_CAP_UNSUPPORTED;
2177     unsigned i;
2178 
2179     PJ_ASSERT_RETURN(dlg && token, PJSIP_DIALOG_CAP_UNKNOWN);
2180 
2181     pjsip_dlg_inc_lock(dlg);
2182 
2183     hdr = (const pjsip_generic_array_hdr*)
2184 	   pjsip_dlg_get_remote_cap_hdr(dlg, htype, hname);
2185     if (!hdr) {
2186 	cap_status = PJSIP_DIALOG_CAP_UNKNOWN;
2187     } else {
2188 	for (i=0; i<hdr->count; ++i) {
2189 	    if (!pj_stricmp(&hdr->values[i], token)) {
2190 		cap_status = PJSIP_DIALOG_CAP_SUPPORTED;
2191 		break;
2192 	    }
2193 	}
2194     }
2195 
2196     pjsip_dlg_dec_lock(dlg);
2197 
2198     return cap_status;
2199 }
2200 
2201 
2202 /*
2203  * Update remote capability of ACCEPT, ALLOW, and SUPPORTED from
2204  * the received message.
2205  */
pjsip_dlg_update_remote_cap(pjsip_dialog * dlg,const pjsip_msg * msg,pj_bool_t strict)2206 PJ_DEF(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
2207 					        const pjsip_msg *msg,
2208 						pj_bool_t strict)
2209 {
2210     pjsip_hdr_e htypes[] =
2211 	{ PJSIP_H_ACCEPT, PJSIP_H_ALLOW, PJSIP_H_SUPPORTED };
2212     unsigned i;
2213 
2214     PJ_ASSERT_RETURN(dlg && msg, PJ_EINVAL);
2215 
2216     pjsip_dlg_inc_lock(dlg);
2217 
2218     /* Retrieve all specified capability header types */
2219     for (i = 0; i < PJ_ARRAY_SIZE(htypes); ++i) {
2220 	const pjsip_generic_array_hdr *hdr;
2221 	pj_status_t status;
2222 
2223 	/* Find this capability type in the message */
2224 	hdr = (const pjsip_generic_array_hdr*)
2225 	      pjsip_msg_find_hdr(msg, htypes[i], NULL);
2226 	if (!hdr) {
2227 	    /* Not found.
2228 	     * If strict update is specified, remote this capability type
2229 	     * from the capability list.
2230 	     */
2231 	    if (strict)
2232 		pjsip_dlg_remove_remote_cap_hdr(dlg, htypes[i], NULL);
2233 	} else {
2234 	    /* Found, a capability type may be specified in multiple headers,
2235 	     * so combine all the capability tags/values into a temporary
2236 	     * header.
2237 	     */
2238 	    pjsip_generic_array_hdr tmp_hdr;
2239 
2240 	    /* Init temporary header */
2241 	    pjsip_generic_array_hdr_init(dlg->pool, &tmp_hdr, NULL);
2242 	    pj_memcpy(&tmp_hdr, hdr, sizeof(pjsip_hdr));
2243 
2244 	    while (hdr) {
2245 		unsigned j;
2246 
2247 		/* Append the header content to temporary header */
2248 		for(j=0; j<hdr->count &&
2249 			 tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j)
2250 		{
2251 		    tmp_hdr.values[tmp_hdr.count++] = hdr->values[j];
2252 		}
2253 
2254 		/* Get the next header for this capability */
2255 		hdr = (const pjsip_generic_array_hdr*)
2256 		      pjsip_msg_find_hdr(msg, htypes[i], hdr->next);
2257 	    }
2258 
2259 	    /* Save this capability */
2260 	    status = pjsip_dlg_set_remote_cap_hdr(dlg, &tmp_hdr);
2261 	    if (status != PJ_SUCCESS) {
2262 		pjsip_dlg_dec_lock(dlg);
2263 		return status;
2264 	    }
2265 	}
2266     }
2267 
2268     pjsip_dlg_dec_lock(dlg);
2269 
2270     return PJ_SUCCESS;
2271 }
2272 
2273 
2274 /*
2275  * Get the value of the specified capability header field of remote.
2276  */
pjsip_dlg_get_remote_cap_hdr(pjsip_dialog * dlg,int htype,const pj_str_t * hname)2277 PJ_DEF(const pjsip_hdr*) pjsip_dlg_get_remote_cap_hdr(pjsip_dialog *dlg,
2278 						      int htype,
2279 						      const pj_str_t *hname)
2280 {
2281     pjsip_hdr *hdr;
2282 
2283     /* Check arguments. */
2284     PJ_ASSERT_RETURN(dlg, NULL);
2285     PJ_ASSERT_RETURN((htype != PJSIP_H_OTHER) || (hname && hname->slen),
2286 		     NULL);
2287 
2288     pjsip_dlg_inc_lock(dlg);
2289 
2290     hdr = dlg->rem_cap_hdr.next;
2291     while (hdr != &dlg->rem_cap_hdr) {
2292 	if ((htype != PJSIP_H_OTHER && htype == hdr->type) ||
2293 	    (htype == PJSIP_H_OTHER && pj_stricmp(&hdr->name, hname) == 0))
2294 	{
2295 	    pjsip_dlg_dec_lock(dlg);
2296 	    return hdr;
2297 	}
2298 	hdr = hdr->next;
2299     }
2300 
2301     pjsip_dlg_dec_lock(dlg);
2302 
2303     return NULL;
2304 }
2305 
2306 
2307 /*
2308  * Set remote capability header from a SIP header containing array
2309  * of capability tags/values.
2310  */
pjsip_dlg_set_remote_cap_hdr(pjsip_dialog * dlg,const pjsip_generic_array_hdr * cap_hdr)2311 PJ_DEF(pj_status_t) pjsip_dlg_set_remote_cap_hdr(
2312 				    pjsip_dialog *dlg,
2313 				    const pjsip_generic_array_hdr *cap_hdr)
2314 {
2315     pjsip_generic_array_hdr *hdr;
2316 
2317     /* Check arguments. */
2318     PJ_ASSERT_RETURN(dlg && cap_hdr, PJ_EINVAL);
2319 
2320     pjsip_dlg_inc_lock(dlg);
2321 
2322     /* Find the header. */
2323     hdr = (pjsip_generic_array_hdr*)
2324 	  pjsip_dlg_get_remote_cap_hdr(dlg, cap_hdr->type, &cap_hdr->name);
2325 
2326     /* Quick compare if the capability is up to date */
2327     if (hdr && hdr->count == cap_hdr->count) {
2328 	unsigned i;
2329 	pj_bool_t uptodate = PJ_TRUE;
2330 
2331 	for (i=0; i<hdr->count; ++i) {
2332 	    if (pj_stricmp(&hdr->values[i], &cap_hdr->values[i]))
2333 		uptodate = PJ_FALSE;
2334 	}
2335 
2336 	/* Capability is up to date, just return PJ_SUCCESS */
2337 	if (uptodate) {
2338 	    pjsip_dlg_dec_lock(dlg);
2339 	    return PJ_SUCCESS;
2340 	}
2341     }
2342 
2343     /* Remove existing capability header if any */
2344     if (hdr)
2345 	pj_list_erase(hdr);
2346 
2347     /* Add the new capability header */
2348     hdr = (pjsip_generic_array_hdr*) pjsip_hdr_clone(dlg->pool, cap_hdr);
2349     hdr->type = cap_hdr->type;
2350     pj_strdup(dlg->pool, &hdr->name, &cap_hdr->name);
2351     pj_list_push_back(&dlg->rem_cap_hdr, hdr);
2352 
2353     pjsip_dlg_dec_lock(dlg);
2354 
2355     /* Done. */
2356     return PJ_SUCCESS;
2357 }
2358 
2359 /*
2360  * Remove a remote capability header.
2361  */
pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog * dlg,int htype,const pj_str_t * hname)2362 PJ_DEF(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg,
2363 						    int htype,
2364 						    const pj_str_t *hname)
2365 {
2366     pjsip_generic_array_hdr *hdr;
2367 
2368     /* Check arguments. */
2369     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
2370     PJ_ASSERT_RETURN((htype != PJSIP_H_OTHER) || (hname && hname->slen),
2371 		     PJ_EINVAL);
2372 
2373     pjsip_dlg_inc_lock(dlg);
2374 
2375     hdr = (pjsip_generic_array_hdr*)
2376 	  pjsip_dlg_get_remote_cap_hdr(dlg, htype, hname);
2377     if (!hdr) {
2378 	pjsip_dlg_dec_lock(dlg);
2379 	return PJ_ENOTFOUND;
2380     }
2381 
2382     pj_list_erase(hdr);
2383 
2384     pjsip_dlg_dec_lock(dlg);
2385 
2386     return PJ_SUCCESS;
2387 }
2388