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, ¬ify)==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, ¶m->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