8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_dialog.c
blob2f65dfae2330fdd517ab5c854c017e7071a83654
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #include <strings.h>
35 #include <sip.h>
37 #include "sip_msg.h"
38 #include "sip_miscdefs.h"
39 #include "sip_hash.h"
40 #include "sip_dialog.h"
41 #include "sip_parse_generic.h"
43 #define SIP_DLG_XCHG_FROM 0
44 #define SIP_DLG_XCHG_TO 1
47 * Dialog state change callback function
49 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
50 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
52 boolean_t sip_incomplete_dialog(sip_dialog_t);
55 * Exchange From/To header
57 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);
60 * Complete dialog hash table
62 sip_hash_t sip_dialog_hash[SIP_HASH_SZ];
65 * Partial dialog hash table
67 sip_hash_t sip_dialog_phash[SIP_HASH_SZ];
70 * Route set structure
72 typedef struct sip_dlg_route_set_s {
73 char *sip_dlg_route;
74 sip_str_t sip_dlg_ruri;
75 boolean_t sip_dlg_route_lr;
76 struct sip_dlg_route_set_s *sip_dlg_route_next;
77 }sip_dlg_route_set_t;
79 sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
80 boolean_t, int);
81 sip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
82 int sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
83 void sip_dialog_delete(_sip_dialog_t *);
84 void sip_dialog_init();
85 sip_dialog_t sip_dialog_find(_sip_msg_t *);
86 boolean_t sip_dialog_match(void *, void *);
87 boolean_t sip_dialog_free(void *, void *, int *);
88 sip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *);
89 char *sip_dialog_req_uri(sip_dialog_t);
91 static void sip_release_dialog_res(_sip_dialog_t *);
92 void sip_dlg_self_destruct(void *);
93 static int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
94 int);
95 static void sip_dialog_free_rset(sip_dlg_route_set_t *);
98 * Timer object for partial dialogs
100 typedef struct sip_dialog_timer_obj_s {
101 _sip_dialog_t *dialog;
102 void (*func)(sip_dialog_t, sip_msg_t, void *);
103 } sip_dialog_timer_obj_t;
106 * To avoid duplication all over the place
108 static void
109 sip_release_dialog_res(_sip_dialog_t *dialog)
111 int count = 0;
112 sip_msg_chain_t *msg_chain;
113 sip_msg_chain_t *nmsg_chain;
115 if (dialog->sip_dlg_ref_cnt != 0) {
116 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
117 SIP_ASSERT_ERROR, __FILE__, __LINE__);
119 assert(dialog->sip_dlg_ref_cnt == 0);
120 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
121 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
122 if (dialog->sip_dlg_call_id != NULL)
123 sip_free_header(dialog->sip_dlg_call_id);
124 if (dialog->sip_dlg_local_uri_tag != NULL)
125 sip_free_header(dialog->sip_dlg_local_uri_tag);
126 if (dialog->sip_dlg_remote_uri_tag != NULL)
127 sip_free_header(dialog->sip_dlg_remote_uri_tag);
128 if (dialog->sip_dlg_remote_target != NULL)
129 sip_free_header(dialog->sip_dlg_remote_target);
130 if (dialog->sip_dlg_local_contact != NULL)
131 sip_free_header(dialog->sip_dlg_local_contact);
132 if (dialog->sip_dlg_new_local_contact != NULL)
133 sip_free_header(dialog->sip_dlg_new_local_contact);
134 if (dialog->sip_dlg_route_set != NULL)
135 sip_free_header(dialog->sip_dlg_route_set);
136 if (dialog->sip_dlg_event != NULL)
137 sip_free_header(dialog->sip_dlg_event);
138 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
139 free(dialog->sip_dlg_req_uri.sip_str_ptr);
140 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
141 dialog->sip_dlg_req_uri.sip_str_len = 0;
143 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
144 free(dialog->sip_dlg_rset.sip_str_ptr);
145 dialog->sip_dlg_rset.sip_str_len = 0;
146 dialog->sip_dlg_rset.sip_str_ptr = NULL;
148 for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
149 msg_chain = dialog->sip_dlg_log[count].sip_msgs;
150 while (msg_chain != NULL) {
151 nmsg_chain = msg_chain->next;
152 if (msg_chain->sip_msg != NULL)
153 free(msg_chain->sip_msg);
154 free(msg_chain);
155 msg_chain = nmsg_chain;
158 (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
159 free(dialog);
163 * Get the route information from the 'value' and add it to the route
164 * set.
166 static sip_dlg_route_set_t *
167 sip_add_route_to_set(sip_hdr_value_t *value)
169 int vlen = 0;
170 sip_dlg_route_set_t *rset;
171 char *crlf;
172 const sip_param_t *uri_param;
173 int error;
175 rset = calloc(1, sizeof (*rset));
176 if (rset == NULL)
177 return (NULL);
178 rset->sip_dlg_route_next = NULL;
179 vlen = value->sip_value_end - value->sip_value_start;
182 * check for CRLF
184 crlf = value->sip_value_end - strlen(SIP_CRLF);
185 while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
186 vlen -= strlen(SIP_CRLF);
187 crlf -= strlen(SIP_CRLF);
189 rset->sip_dlg_route = calloc(1, vlen + 1);
190 if (rset->sip_dlg_route == NULL) {
191 free(rset);
192 return (NULL);
195 * loose routing
197 rset->sip_dlg_route_lr = B_FALSE;
198 (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);
199 rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +
200 (value->cftr_uri.sip_str_ptr - value->sip_value_start);
201 rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;
202 rset->sip_dlg_route[vlen] = '\0';
204 assert(value->sip_value_parsed_uri != NULL);
206 * Check if the 'lr' param is present for this route.
208 uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);
209 if (error != 0) {
210 free(rset->sip_dlg_route);
211 free(rset);
212 return (NULL);
214 if (uri_param != NULL) {
215 rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",
216 strlen("lr"));
218 return (rset);
222 * Depending on the route-set, determine the request URI.
224 char *
225 sip_dialog_req_uri(sip_dialog_t dialog)
227 const sip_str_t *req_uri;
228 char *uri;
229 _sip_dialog_t *_dialog;
231 _dialog = (_sip_dialog_t *)dialog;
232 if (_dialog->sip_dlg_route_set == NULL ||
233 _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
234 const struct sip_value *val;
236 val = sip_get_header_value(_dialog->sip_dlg_remote_target,
237 NULL);
238 if (val == NULL)
239 return (NULL);
240 req_uri = &((sip_hdr_value_t *)val)->cftr_uri;
241 } else {
242 req_uri = &_dialog->sip_dlg_req_uri;
244 uri = (char *)malloc(req_uri->sip_str_len + 1);
245 if (uri == NULL)
246 return (NULL);
247 (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);
248 uri[req_uri->sip_str_len] = '\0';
250 return (uri);
254 * Free the route set.
256 void
257 sip_dialog_free_rset(sip_dlg_route_set_t *rset)
259 sip_dlg_route_set_t *next;
261 while (rset != NULL) {
262 next = rset->sip_dlg_route_next;
263 rset->sip_dlg_route_next = NULL;
264 free(rset->sip_dlg_route);
265 free(rset);
266 rset = next;
271 * Recompute route-set
273 static int
274 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
276 int ret;
278 if (dialog->sip_dlg_route_set != NULL) {
279 sip_free_header(dialog->sip_dlg_route_set);
280 dialog->sip_dlg_route_set = NULL;
282 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
283 free(dialog->sip_dlg_req_uri.sip_str_ptr);
284 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
285 dialog->sip_dlg_req_uri.sip_str_len = 0;
287 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
288 free(dialog->sip_dlg_rset.sip_str_ptr);
289 dialog->sip_dlg_rset.sip_str_ptr = NULL;
290 dialog->sip_dlg_rset.sip_str_len = 0;
292 ret = sip_dialog_get_route_set(dialog, sip_msg, what);
293 return (ret);
297 * If the route set is empty, the UAC MUST place the remote target URI
298 * into the Request-URI. The UAC MUST NOT add a Route header field to
299 * the request.
301 * If the route set is not empty, and the first URI in the route set
302 * contains the lr parameter (see Section 19.1.1), the UAC MUST place
303 * the remote target URI into the Request-URI and MUST include a Route
304 * header field containing the route set values in order, including all
305 * parameters.
307 * If the route set is not empty, and its first URI does not contain the
308 * lr parameter, the UAC MUST place the first URI from the route set
309 * into the Request-URI, stripping any parameters that are not allowed
310 * in a Request-URI. The UAC MUST add a Route header field containing
311 * the remainder of the route set values in order, including all
312 * parameters. The UAC MUST then place the remote target URI into the
313 * Route header field as the last value.
316 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
317 int rcnt, int rlen)
319 size_t rset_len;
320 _sip_header_t *rhdr;
321 char *rset;
322 char *rp;
323 char *rsp;
324 int count;
325 sip_dlg_route_set_t *route;
326 boolean_t first = B_TRUE;
327 const sip_str_t *to_uri;
328 char *uri = NULL;
329 int rspl;
330 int rpl;
332 if (rcnt <= 0) {
333 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
334 SIP_ASSERT_ERROR, __FILE__, __LINE__);
336 assert(rcnt > 0);
338 dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
339 dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);
340 if (dialog->sip_dlg_rset.sip_str_ptr == NULL)
341 return (ENOMEM);
342 rsp = dialog->sip_dlg_rset.sip_str_ptr;
343 rspl = rlen + rcnt;
344 route = rset_head;
345 rset_len = rlen;
346 if (!route->sip_dlg_route_lr) {
347 const struct sip_value *val;
349 val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);
350 to_uri = &((sip_hdr_value_t *)val)->cftr_uri;
351 uri = (char *)malloc(to_uri->sip_str_len + 1);
352 if (uri == NULL) {
353 free(dialog->sip_dlg_rset.sip_str_ptr);
354 dialog->sip_dlg_rset.sip_str_len = 0;
355 dialog->sip_dlg_rset.sip_str_ptr = NULL;
356 return (ENOMEM);
358 (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);
359 uri[to_uri->sip_str_len] = '\0';
360 rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +
361 SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
362 sizeof (char);
363 count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);
364 dialog->sip_dlg_req_uri.sip_str_ptr = malloc(
365 route->sip_dlg_ruri.sip_str_len + 1);
366 if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
367 free(uri);
368 free(dialog->sip_dlg_rset.sip_str_ptr);
369 dialog->sip_dlg_rset.sip_str_len = 0;
370 dialog->sip_dlg_rset.sip_str_ptr = NULL;
371 return (ENOMEM);
373 (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +
374 (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),
375 route->sip_dlg_ruri.sip_str_len);
376 dialog->sip_dlg_req_uri.sip_str_ptr[
377 route->sip_dlg_ruri.sip_str_len] = '\0';
378 dialog->sip_dlg_req_uri.sip_str_len =
379 route->sip_dlg_ruri.sip_str_len;
381 rsp += count;
382 rspl -= count;
383 route = route->sip_dlg_route_next;
387 * rcnt - 1 is for the number of COMMAs
389 rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) +
390 SIP_SPACE_LEN + rcnt - 1;
391 rset = malloc(rset_len + 1);
392 if (rset == NULL) {
393 free(dialog->sip_dlg_rset.sip_str_ptr);
394 dialog->sip_dlg_rset.sip_str_len = 0;
395 dialog->sip_dlg_rset.sip_str_ptr = NULL;
396 return (ENOMEM);
398 rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));
399 if (rhdr == NULL) {
400 free(rset);
401 free(dialog->sip_dlg_rset.sip_str_ptr);
402 dialog->sip_dlg_rset.sip_str_len = 0;
403 dialog->sip_dlg_rset.sip_str_ptr = NULL;
404 return (ENOMEM);
407 rp = rset;
408 rpl = rset_len + 1;
409 count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);
410 rp += count;
411 rpl -= count;
413 while (route != NULL) {
414 if (first) {
415 count = snprintf(rp, rpl, "%s", route->sip_dlg_route);
416 rp += count;
417 rpl -= count;
418 first = B_FALSE;
419 if (uri != NULL) {
420 count = snprintf(rsp, rspl, "%c%s",
421 SIP_COMMA, route->sip_dlg_route);
422 } else {
423 count = snprintf(rsp, rspl, "%s",
424 route->sip_dlg_route);
426 rsp += count;
427 rspl -= count;
428 } else {
429 count = snprintf(rp, rpl, "%c%s", SIP_COMMA,
430 route->sip_dlg_route);
431 rp += count;
432 rpl -= count;
433 count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,
434 route->sip_dlg_route);
435 rsp += count;
436 rspl -= count;
438 route = route->sip_dlg_route_next;
440 if (rsp > dialog->sip_dlg_rset.sip_str_ptr +
441 dialog->sip_dlg_rset.sip_str_len) {
442 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
443 SIP_ASSERT_ERROR, __FILE__, __LINE__);
445 assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
446 dialog->sip_dlg_rset.sip_str_len);
447 dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
448 '\0';
449 if (uri != NULL) {
450 if (first) {
451 count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,
452 uri, SIP_RAQUOT);
453 } else {
454 count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,
455 SIP_LAQUOT, uri, SIP_RAQUOT);
457 rp += count;
458 rpl -= count;
459 free(uri);
461 if (rp > rset + rset_len) {
462 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
463 SIP_ASSERT_ERROR, __FILE__, __LINE__);
465 assert(rp <= rset + rset_len);
466 (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
467 "%s%s", rset, SIP_CRLF);
468 free(rset);
469 dialog->sip_dlg_route_set = (sip_header_t)rhdr;
470 sip_dialog_free_rset(rset_head);
471 return (0);
475 * UAC Behavior
476 * The route set MUST be set to the list of URIs in the Record-Route
477 * header field from the response, taken in reverse order and preserving
478 * all URI parameters.
480 * UAS behavior
481 * The route set MUST be set to the list of URIs in the Record-Route
482 * header field from the request, taken in order and preserving all URI
483 * parameters.
485 static int
486 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
488 sip_header_t rrhdr;
489 sip_hdr_value_t *value;
490 int error;
491 sip_dlg_route_set_t *rset_head = NULL;
492 sip_dlg_route_set_t *rset_tail = NULL;
493 sip_dlg_route_set_t *rset;
494 int rset_cnt = 0;
495 int rset_len = 0;
497 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
498 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);
499 while (rrhdr != NULL) {
500 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
501 value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);
502 while (value != NULL && error == 0) {
503 char *crlf;
505 if (value->sip_value_state == SIP_VALUE_BAD) {
506 value = (sip_hdr_value_t *)sip_get_next_value(
507 (sip_header_value_t)value, &error);
508 continue;
510 rset = sip_add_route_to_set(value);
511 if (rset == NULL)
512 goto r_error;
514 * Add one for COMMA
516 rset_cnt++;
517 rset_len += (value->sip_value_end -
518 value->sip_value_start);
520 * Check for CRLF
522 crlf = value->sip_value_end - strlen(SIP_CRLF);
523 while (crlf != NULL &&
524 strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
525 rset_len -= strlen(SIP_CRLF);
526 crlf -= strlen(SIP_CRLF);
528 if (rset_head == NULL) {
529 if (rset_tail != NULL) {
530 sip_write_to_log((void *)dialog,
531 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
532 __FILE__, __LINE__);
534 assert(rset_tail == NULL);
535 rset_head = rset_tail = rset;
536 } else if (what == SIP_UAS_DIALOG) {
537 rset_tail->sip_dlg_route_next = rset;
538 rset_tail = rset;
539 } else if (what == SIP_UAC_DIALOG) {
540 rset->sip_dlg_route_next = rset_head;
541 rset_head = rset;
542 } else {
543 sip_write_to_log((void *)dialog,
544 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
545 __FILE__, __LINE__);
546 assert(0);
548 value = (sip_hdr_value_t *)sip_get_next_value(
549 (sip_header_value_t)value, &error);
551 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
552 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);
554 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
555 if (rset_cnt == 0)
556 return (0);
557 if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,
558 rset_len) != 0) {
559 goto r_error;
561 return (0);
562 r_error:
563 sip_dialog_free_rset(rset_head);
564 return (ENOMEM);
568 * UAS behavior:
569 * The remote sequence number MUST be set to the value of the sequence
570 * number in the CSeq header field of the request. The local sequence
571 * number MUST be empty. The call identifier component of the dialog ID
572 * MUST be set to the value of the Call-ID in the request. The local
573 * tag component of the dialog ID MUST be set to the tag in the To field
574 * in the response to the request (which always includes a tag), and the
575 * remote tag component of the dialog ID MUST be set to the tag from the
576 * From field in the request. A UAS MUST be prepared to receive a
577 * request without a tag in the From field, in which case the tag is
578 * considered to have a value of null.
579 * The remote URI MUST be set to the URI in the From field, and the
580 * local URI MUST be set to the URI in the To field.
581 * The remote target MUST be set to the URI from the Contact header field
582 * of the request.
584 * UAC behavior:
585 * The local sequence number MUST be set to the value of the sequence
586 * number in the CSeq header field of the request. The remote sequence
587 * number MUST be empty (it is established when the remote UA sends a
588 * request within the dialog). The call identifier component of the
589 * dialog ID MUST be set to the value of the Call-ID in the request.
590 * The local tag component of the dialog ID MUST be set to the tag in
591 * the From field in the request, and the remote tag component of the
592 * dialog ID MUST be set to the tag in the To field of the response. A
593 * UAC MUST be prepared to receive a response without a tag in the To
594 * field, in which case the tag is considered to have a value of null.
595 * The remote URI MUST be set to the URI in the To field, and the local
596 * URI MUST be set to the URI in the From field.
597 * The remote target MUST be set to the URI from the Contact header field
598 * of the response.
603 * This is the routine that seeds a dialog.
605 sip_dialog_t
606 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
607 boolean_t dlg_on_fork, int dlg_type)
609 _sip_dialog_t *dialog;
610 int cseq;
611 sip_header_t fhdr = NULL;
612 sip_header_t thdr = NULL;
613 sip_header_t chdr;
614 sip_header_t cihdr;
615 sip_header_t evhdr = NULL;
616 const struct sip_value *value;
617 sip_dialog_timer_obj_t *tim_obj = NULL;
618 const sip_str_t *callid;
619 sip_method_t method;
620 int timer1 = sip_timer_T1;
621 int error;
623 if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))
624 return (NULL);
626 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
628 * Only INVITE and SUBSCRIBE supported
630 if (error != 0 || (method != INVITE && method != SUBSCRIBE))
631 return (NULL);
634 * A request outside of a dialog MUST NOT contain a To tag
636 if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL)
637 return (NULL);
639 if (dlg_type == SIP_UAS_DIALOG) {
640 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
641 SIP_DLG_XCHG_FROM);
642 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
643 } else {
644 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
645 fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);
647 cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);
648 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
649 if (method == SUBSCRIBE)
650 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
651 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
652 if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||
653 (method == SUBSCRIBE && evhdr == NULL)) {
654 if (thdr != NULL)
655 sip_free_header(thdr);
656 return (NULL);
660 * Sanity check since we just store the headers in the dialog
662 if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||
663 sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
664 ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||
665 (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||
666 sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
667 ((value = sip_get_header_value(chdr, NULL)) == NULL) ||
668 sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {
669 if (thdr != NULL)
670 sip_free_header(thdr);
671 return (NULL);
674 tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t));
675 if (tim_obj == NULL) {
676 if (thdr != NULL)
677 sip_free_header(thdr);
678 return (NULL);
680 dialog = calloc(1, sizeof (_sip_dialog_t));
681 if (dialog == NULL) {
682 if (thdr != NULL)
683 sip_free_header(thdr);
684 return (NULL);
687 * We will take the TO header with the tag when we complete this
688 * dialog
690 if (dlg_type == SIP_UAS_DIALOG) {
691 dialog->sip_dlg_remote_uri_tag = thdr;
693 * We take the remote target from the incoming request on the
694 * UAS. For the UAC, we will take it from the response.
696 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) ==
697 NULL) {
698 goto dia_err;
700 } else {
701 if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==
702 NULL) {
703 goto dia_err;
706 * We take the local contact from the originating request on
707 * UAC. For the UAS, we will take it from the response.
709 if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) ==
710 NULL) {
711 goto dia_err;
712 } else {
713 dialog->sip_dlg_new_local_contact = NULL;
716 if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
717 goto dia_err;
718 if (method == SUBSCRIBE) {
719 dialog->sip_dlg_event = sip_dup_header(evhdr);
720 if (dialog->sip_dlg_event == NULL) {
721 goto dia_err;
724 dialog->sip_dlg_rset.sip_str_ptr = NULL;
725 dialog->sip_dlg_rset.sip_str_len = 0;
726 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
727 dialog->sip_dlg_req_uri.sip_str_len = 0;
729 * Get the route set from the request, if present
731 if (dlg_type == SIP_UAS_DIALOG &&
732 sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {
733 goto dia_err;
735 if (dlg_type == SIP_UAC_DIALOG)
736 dialog->sip_dlg_local_cseq = cseq;
737 else
738 dialog->sip_dlg_remote_cseq = cseq;
739 dialog->sip_dlg_type = dlg_type;
740 dialog->sip_dlg_on_fork = dlg_on_fork;
741 dialog->sip_dlg_method = method;
743 * Set the partial dialog timer with the INVITE timeout val
745 if (sip_conn_timer1 != NULL)
746 timer1 = sip_conn_timer1(obj);
747 SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);
748 tim_obj->dialog = dialog;
750 * Since at the client we never pass the partial dialog, we need not
751 * invoke the callback when the partial dialog self-destructs.
753 if (dlg_type == SIP_UAS_DIALOG)
754 tim_obj->func = sip_ulp_dlg_del_cb;
755 SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,
756 sip_dlg_self_destruct);
757 if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
758 goto dia_err;
759 (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);
761 if (dlg_type == SIP_UAC_DIALOG) {
762 const sip_str_t *local_tag;
764 local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
765 if (local_tag == NULL) {
766 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
767 SIP_ASSERT_ERROR, __FILE__, __LINE__);
769 assert(local_tag != NULL);
770 sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,
771 callid->sip_str_ptr, callid->sip_str_len,
772 NULL, 0, NULL, 0, NULL, 0, NULL, 0,
773 (uchar_t *)dialog->sip_dlg_id);
777 * Add it to the partial hash table
779 if (sip_hash_add(sip_dialog_phash, (void *)dialog,
780 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
781 goto dia_err;
785 dialog->sip_dlg_msgcnt = 1;
786 sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
787 (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
789 SIP_DLG_REFCNT_INCR(dialog);
790 return ((sip_dialog_t)dialog);
791 dia_err:
792 sip_release_dialog_res(dialog);
793 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
794 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
795 if (tim_obj != NULL)
796 free(tim_obj);
797 return (NULL);
801 * When creating a dialog from a NOTIFY request, we need to get the FROM
802 * header for the dialog from the TO header of the NOTIFY.
804 _sip_header_t *
805 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what)
807 int len;
808 _sip_header_t *newhdr;
809 int cnt;
810 const struct sip_header *hdr;
811 int hdrsize;
812 int error;
814 hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :
815 SIP_TO, NULL, &error);
816 if (error != 0 || hdr == NULL)
817 return (NULL);
818 if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)
819 return (NULL);
820 len = hdr->sip_hdr_end - hdr->sip_hdr_current;
821 if (what == SIP_DLG_XCHG_FROM) {
822 hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) +
823 SIP_SPACE_LEN;
824 } else {
825 hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN +
826 sizeof (char) + SIP_SPACE_LEN;
828 newhdr = sip_new_header(hdrsize);
829 if (newhdr == NULL)
830 return (NULL);
831 if (what == SIP_DLG_XCHG_FROM) {
832 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
833 "%s %c ", SIP_TO, SIP_HCOLON);
834 } else {
835 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
836 "%s %c ", SIP_FROM, SIP_HCOLON);
838 newhdr->sip_hdr_current += cnt;
839 (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);
840 newhdr->sip_hdr_current += len;
841 assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);
842 assert(hdr->sip_header_functions != NULL);
845 * FROM and TO have common parsing functions
847 newhdr->sip_header_functions = hdr->sip_header_functions;
848 newhdr->sip_hdr_current = newhdr->sip_hdr_start;
850 return (newhdr);
854 * This is the response that completes the dialog that was created
855 * in sip_seed_dialog().
857 sip_dialog_t
858 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
860 _sip_header_t *thdr;
861 _sip_header_t *evhdr = NULL;
862 _sip_header_t *substate = NULL;
863 sip_header_t chdr = NULL;
864 int resp_code;
865 const sip_str_t *ttag;
866 const sip_str_t *remtag;
867 const sip_str_t *callid;
868 const struct sip_value *val;
869 sip_method_t method;
870 int error = 0;
871 int prev_state;
872 boolean_t alloc_thdr = B_FALSE;
874 if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)
875 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
876 else
877 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
878 if (error != 0 || dialog == NULL ||
879 (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&
880 (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {
881 return (NULL);
883 if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&
884 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
885 dialog->sip_dlg_local_cseq) ||
886 (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&
887 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
888 dialog->sip_dlg_remote_cseq)) {
889 return (NULL);
891 if (method == NOTIFY) {
892 const sip_str_t *sstate;
894 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
895 SIP_DLG_XCHG_FROM);
896 if (thdr == NULL)
897 return (NULL);
898 alloc_thdr = B_TRUE;
899 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
900 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
901 if (chdr == NULL) {
902 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
903 sip_free_header(thdr);
904 return (NULL);
906 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
907 if (evhdr == NULL) {
908 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
909 sip_free_header(thdr);
910 return (NULL);
912 substate = sip_search_for_header(sip_msg,
913 SIP_SUBSCRIPTION_STATE, NULL);
914 if (substate == NULL) {
915 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
916 sip_free_header(thdr);
917 return (NULL);
919 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
920 sstate = sip_get_substate((sip_msg_t)sip_msg, &error);
921 if (sstate == NULL || error != 0) {
922 sip_free_header(thdr);
923 return (NULL);
925 if ((sstate->sip_str_len != strlen("pending") &&
926 sstate->sip_str_len != strlen("active")) ||
927 ((sstate->sip_str_len == strlen("pending") &&
928 strncasecmp(sstate->sip_str_ptr, "pending",
929 strlen("pending")) != 0) ||
930 (sstate->sip_str_len == strlen("active") &&
931 strncasecmp(sstate->sip_str_ptr, "active",
932 strlen("active")) != 0))) {
933 sip_free_header(thdr);
934 return (NULL);
936 ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
937 } else {
938 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
939 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
940 SIP_DLG_XCHG_TO);
941 alloc_thdr = B_TRUE;
942 } else {
943 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
944 thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);
945 if (dialog->sip_dlg_remote_target == NULL) {
946 chdr = sip_search_for_header(sip_msg,
947 SIP_CONTACT, NULL);
949 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
951 if (thdr == NULL) {
952 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
953 return (NULL);
955 ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);
957 if (ttag == NULL) {
958 if (alloc_thdr)
959 sip_free_header(thdr);
960 return (NULL);
962 prev_state = dialog->sip_dlg_state;
964 if (method == NOTIFY) {
965 int error;
966 const sip_str_t *dlg_id_val = NULL;
967 const sip_str_t *event;
968 const sip_str_t *id_val = NULL;
969 sip_header_value_t ev_val;
970 sip_hdr_value_t *dlg_ev_val = NULL;
972 event = sip_get_event((sip_msg_t)sip_msg, &error);
973 if (event == NULL || error != 0) {
974 sip_free_header(thdr);
975 return (NULL);
977 ev_val = (sip_header_value_t)sip_get_header_value(evhdr,
978 &error);
979 if (ev_val != NULL)
980 id_val = sip_get_param_value(ev_val, "id", &error);
981 if (error == 0) {
982 dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(
983 dialog->sip_dlg_event, &error);
985 if (dlg_ev_val == NULL || error != 0) {
986 sip_free_header(thdr);
987 return (NULL);
989 dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,
990 "id", &error);
991 if (error != 0 ||
992 dlg_ev_val->str_val_len != event->sip_str_len ||
993 strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,
994 event->sip_str_len != 0)) {
995 sip_free_header(thdr);
996 return (NULL);
998 if ((dlg_id_val == NULL && id_val != NULL) ||
999 (dlg_id_val != NULL && id_val == NULL)) {
1000 sip_free_header(thdr);
1001 return (NULL);
1002 } else if (dlg_id_val != NULL && id_val != NULL) {
1003 if (dlg_id_val->sip_str_len != id_val->sip_str_len ||
1004 strncasecmp(dlg_id_val->sip_str_ptr,
1005 id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=
1006 0) {
1007 sip_free_header(thdr);
1008 return (NULL);
1011 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1012 dialog->sip_dlg_remote_uri_tag = thdr;
1013 if ((dialog->sip_dlg_remote_target =
1014 sip_dup_header(chdr)) == NULL) {
1015 sip_free_header(thdr);
1016 return (NULL);
1018 } else {
1019 dialog->sip_dlg_local_uri_tag = thdr;
1021 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1022 } else {
1023 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1024 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1025 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1026 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1027 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1029 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1030 if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
1031 if (dialog->sip_dlg_type != SIP_UAC_DIALOG) {
1032 sip_write_to_log((void *)dialog,
1033 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
1034 __FILE__, __LINE__);
1036 assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
1037 if ((dialog->sip_dlg_remote_target =
1038 sip_dup_header(chdr)) == NULL) {
1039 (void) pthread_mutex_unlock(
1040 &dialog->sip_dlg_mutex);
1041 if (alloc_thdr)
1042 sip_free_header(thdr);
1043 goto terminate_new_dlg;
1045 if (sip_dialog_get_route_set(dialog, sip_msg,
1046 dialog->sip_dlg_type) != 0) {
1047 (void) pthread_mutex_unlock(
1048 &dialog->sip_dlg_mutex);
1049 if (alloc_thdr)
1050 sip_free_header(thdr);
1051 goto terminate_new_dlg;
1054 if (SIP_PROVISIONAL_RESP(resp_code)) {
1055 dialog->sip_dlg_state = SIP_DLG_EARLY;
1056 } else if (SIP_OK_RESP(resp_code)) {
1058 * Per 12.1 the UAS must include the contact header
1059 * for a dialog establishing response, so if we
1060 * don't find one, we terminate it.
1062 if (dialog->sip_dlg_remote_target == NULL) {
1063 (void) pthread_mutex_unlock(
1064 &dialog->sip_dlg_mutex);
1065 if (sip_ulp_dlg_del_cb != NULL) {
1066 sip_ulp_dlg_del_cb(dialog,
1067 (sip_msg_t)sip_msg, NULL);
1069 if (alloc_thdr)
1070 sip_free_header(thdr);
1071 goto terminate_new_dlg;
1073 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1074 } else {
1075 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1076 if (sip_ulp_dlg_del_cb != NULL) {
1077 sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg,
1078 NULL);
1080 if (alloc_thdr)
1081 sip_free_header(thdr);
1082 goto terminate_new_dlg;
1084 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1085 dialog->sip_dlg_local_uri_tag = thdr;
1086 } else {
1087 if ((dialog->sip_dlg_remote_uri_tag =
1088 sip_dup_header(thdr)) == NULL) {
1089 (void) pthread_mutex_unlock(
1090 &dialog->sip_dlg_mutex);
1091 goto terminate_new_dlg;
1097 * We take the local contact for UAS Dialog from the response (either
1098 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE
1099 * request)
1101 if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state
1102 == SIP_DLG_CONFIRMED)) {
1103 if (chdr == NULL) {
1104 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1105 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1106 NULL);
1107 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1109 if ((chdr == NULL) || ((dialog->sip_dlg_local_contact =
1110 sip_dup_header(chdr)) == NULL)) {
1111 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1112 if (alloc_thdr)
1113 sip_free_header(thdr);
1114 goto terminate_new_dlg;
1119 * Cancel the partial dialog timer
1121 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1122 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1124 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1125 val = sip_get_header_value(dialog->sip_dlg_local_uri_tag,
1126 &error);
1127 } else {
1128 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
1129 &error);
1131 if (val == NULL || error != 0) {
1132 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1133 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1135 assert(val != NULL && error == 0);
1136 remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
1138 val = sip_get_header_value(dialog->sip_dlg_call_id, &error);
1139 callid = &((sip_hdr_value_t *)val)->str_val;
1142 * Get an ID for this dialog
1144 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1145 sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,
1146 ttag->sip_str_ptr, ttag->sip_str_len,
1147 callid->sip_str_ptr, callid->sip_str_len,
1148 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1149 } else {
1150 sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len,
1151 remtag->sip_str_ptr, remtag->sip_str_len,
1152 callid->sip_str_ptr, callid->sip_str_len,
1153 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1156 SIP_DLG_REFCNT_INCR(dialog);
1157 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1160 * Add it to the hash table
1162 if (sip_hash_add(sip_dialog_hash, (void *)dialog,
1163 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
1164 terminate_new_dlg:
1166 * So that sip_dialog_delete() does not try to remove
1167 * this from the hash table.
1169 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1170 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1171 if (dialog->sip_dlg_local_uri_tag != NULL) {
1172 sip_free_header(dialog->sip_dlg_local_uri_tag);
1173 dialog->sip_dlg_local_uri_tag = NULL;
1175 } else {
1176 if (dialog->sip_dlg_remote_uri_tag != NULL) {
1177 sip_free_header(dialog->sip_dlg_remote_uri_tag);
1178 dialog->sip_dlg_remote_uri_tag = NULL;
1181 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1182 sip_dialog_terminate(dialog, (sip_msg_t)sip_msg);
1183 return (NULL);
1185 if (sip_dlg_ulp_state_cb != NULL) {
1186 sip_dlg_ulp_state_cb((sip_dialog_t)dialog,
1187 (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);
1189 return ((sip_dialog_t)dialog);
1193 * Check if this dialog is a match.
1195 boolean_t
1196 sip_dialog_match(void *obj, void *hindex)
1198 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1200 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1201 if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1202 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1203 return (B_FALSE);
1205 if (bcmp(dialog->sip_dlg_id, hindex,
1206 sizeof (dialog->sip_dlg_id)) == 0) {
1207 SIP_DLG_REFCNT_INCR(dialog);
1208 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1209 return (B_TRUE);
1211 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1212 return (B_FALSE);
1216 * Don't delete, just take it out of the hash
1218 boolean_t
1219 sip_dialog_dontfree(void *obj, void *hindex, int *found)
1221 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1223 *found = 0;
1224 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1225 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1226 == 0) {
1227 *found = 1;
1228 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1229 return (B_TRUE);
1231 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1232 return (B_FALSE);
1236 * Free resources associated with the dialog, the object will be removed
1237 * from the hash list by sip_hash_delete.
1239 boolean_t
1240 sip_dialog_free(void *obj, void *hindex, int *found)
1242 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1244 *found = 0;
1245 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1246 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1247 == 0) {
1248 *found = 1;
1249 if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) {
1250 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1251 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1253 assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);
1254 if (dialog->sip_dlg_ref_cnt != 0) {
1255 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1256 return (B_FALSE);
1258 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1259 sip_release_dialog_res(dialog);
1260 return (B_TRUE);
1262 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1263 return (B_FALSE);
1267 * The UAS will receive the request from the transaction layer. If the
1268 * request has a tag in the To header field, the UAS core computes the
1269 * dialog identifier corresponding to the request and compares it with
1270 * existing dialogs. If there is a match, this is a mid-dialog request.
1272 sip_dialog_t
1273 sip_dialog_find(_sip_msg_t *sip_msg)
1275 const sip_str_t *localtag;
1276 const sip_str_t *remtag;
1277 const sip_str_t *callid;
1278 uint16_t digest[8];
1279 _sip_dialog_t *dialog;
1280 boolean_t is_request;
1281 int error;
1283 is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1284 if (error != 0)
1285 return (NULL);
1286 if (is_request) {
1287 localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1288 if (error == 0)
1289 remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1290 } else {
1291 remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1292 if (error == 0)
1293 localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1295 if (error != 0)
1296 return (NULL);
1297 callid = sip_get_callid((sip_msg_t)sip_msg, &error);
1298 if (error != 0 || remtag == NULL || localtag == NULL ||
1299 callid == NULL) {
1300 return (NULL);
1302 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1303 remtag->sip_str_ptr, remtag->sip_str_len,
1304 callid->sip_str_ptr, callid->sip_str_len,
1305 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1307 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,
1308 (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);
1309 if (dialog == NULL) {
1310 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1311 NULL, 0, callid->sip_str_ptr, callid->sip_str_len,
1312 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1313 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,
1314 (void *)digest, SIP_DIGEST_TO_HASH(digest),
1315 sip_dialog_match);
1317 return ((sip_dialog_t)dialog);
1321 * We keep this partial dialog for the duration of the INVITE
1322 * transaction timeout duration, i.e. Timer B.
1324 void
1325 sip_dlg_self_destruct(void *args)
1327 sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args;
1328 _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog;
1329 int index;
1331 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1332 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1333 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1334 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1336 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1337 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1338 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1339 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1340 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1341 sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,
1342 index, sip_dialog_dontfree);
1343 } else {
1344 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1346 if (tim_obj->func != NULL)
1347 tim_obj->func(dialog, NULL, NULL);
1348 free(tim_obj);
1349 SIP_DLG_REFCNT_DECR(dialog);
1353 * Terminate a dialog
1355 void
1356 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg)
1358 int prev_state;
1360 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1361 prev_state = dialog->sip_dlg_state;
1362 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1363 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1364 if (sip_dlg_ulp_state_cb != NULL) {
1365 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,
1366 dialog->sip_dlg_state);
1368 SIP_DLG_REFCNT_DECR(dialog);
1372 * Delete a dialog
1374 void
1375 sip_dialog_delete(_sip_dialog_t *dialog)
1377 int index;
1380 * partial dialog, not in the hash table
1382 if (dialog->sip_dlg_local_uri_tag == NULL ||
1383 dialog->sip_dlg_remote_uri_tag == NULL) {
1385 * Cancel the partial dialog timer
1387 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1388 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1389 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1390 sip_release_dialog_res(dialog);
1391 return;
1393 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1394 sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,
1395 sip_dialog_free);
1399 * Get the remote target from the CONTACT header from the 200 OK response
1401 static boolean_t
1402 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg)
1404 sip_header_t chdr;
1406 if (dialog->sip_dlg_remote_target != NULL)
1407 return (B_TRUE);
1409 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1410 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1411 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1412 if (chdr == NULL)
1413 return (B_FALSE);
1414 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL)
1415 return (B_FALSE);
1417 return (B_TRUE);
1421 * Process an incoming request/response
1423 /* ARGSUSED */
1425 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
1427 boolean_t request;
1428 _sip_dialog_t *_dialog;
1429 int error;
1431 _dialog = (_sip_dialog_t *)*sip_dialog;
1433 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1434 _dialog->sip_dlg_msgcnt++;
1435 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1436 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1437 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1439 request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1440 if (error != 0)
1441 return (EINVAL);
1442 if (request) {
1443 uint32_t cseq;
1444 sip_method_t method;
1446 cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error);
1447 if (error != 0)
1448 return (EINVAL);
1449 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1450 if (error != 0)
1451 return (EINVAL);
1452 if (sip_get_request_method((sip_msg_t)sip_msg, &error) !=
1453 method) {
1454 return (EINVAL);
1456 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1458 * Requests that do not change in any way the state
1459 * of a dialog may be received within a dialog.
1460 * They are processed as if they had been received
1461 * outside the dialog.
1462 * For dialogs that have been established with an
1463 * INVITE, the only target refresh request defined is
1464 * re-INVITE.
1466 if (_dialog->sip_dlg_method == INVITE &&
1467 method == INVITE && _dialog->sip_dlg_remote_cseq != 0 &&
1468 SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) {
1469 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1470 return (EPROTO);
1473 * Target-Refresh request
1475 if (_dialog->sip_dlg_method == INVITE && method == INVITE) {
1476 sip_header_t chdr;
1477 sip_header_t nchdr;
1479 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1480 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1481 NULL);
1482 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1483 if (chdr != NULL &&
1484 (nchdr = sip_dup_header(chdr)) != NULL) {
1485 if (_dialog->sip_dlg_remote_target != NULL) {
1486 sip_free_header(
1487 _dialog->sip_dlg_remote_target);
1489 _dialog->sip_dlg_remote_target = nchdr;
1492 _dialog->sip_dlg_remote_cseq = cseq;
1493 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1494 } else {
1495 int resp_code;
1496 sip_method_t method;
1497 int error;
1499 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1500 if (error == 0) {
1501 method = sip_get_callseq_method((sip_msg_t)sip_msg,
1502 &error);
1504 if (error != 0)
1505 return (error);
1507 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1508 if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1509 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1510 return (0);
1512 if (_dialog->sip_dlg_state != SIP_DLG_EARLY &&
1513 _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) {
1514 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1515 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1517 assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
1518 _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
1520 * Let the user delete the dialog if it is not a 1XX/2XX resp
1521 * for an early INVITE dialog.
1523 if (SIP_OK_RESP(resp_code)) {
1524 if (method == INVITE) {
1525 if (!sip_get_rtarg(_dialog, sip_msg)) {
1526 (void) pthread_mutex_unlock(
1527 &_dialog->sip_dlg_mutex);
1528 if (sip_ulp_dlg_del_cb != NULL) {
1529 sip_ulp_dlg_del_cb(
1530 (sip_dialog_t)_dialog,
1531 (sip_msg_t)sip_msg, NULL);
1533 sip_dialog_terminate(_dialog,
1534 (sip_msg_t)sip_msg);
1535 return (0);
1537 if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1538 _dialog->sip_dlg_state =
1539 SIP_DLG_CONFIRMED;
1540 (void) sip_dlg_recompute_rset(_dialog,
1541 sip_msg, SIP_UAC_DIALOG);
1542 (void) pthread_mutex_unlock(
1543 &_dialog->sip_dlg_mutex);
1544 if (sip_dlg_ulp_state_cb != NULL) {
1545 sip_dlg_ulp_state_cb(
1546 (sip_dialog_t)_dialog,
1547 sip_msg, SIP_DLG_EARLY,
1548 _dialog->sip_dlg_state);
1550 return (0);
1551 } else if (_dialog->sip_dlg_new_local_contact
1552 != NULL) {
1553 if (_dialog->sip_dlg_local_contact ==
1554 NULL) {
1555 (void) sip_write_to_log((void *)
1556 _dialog, SIP_DIALOG_LOG |
1557 SIP_ASSERT_ERROR, __FILE__,
1558 __LINE__);
1560 assert(_dialog->sip_dlg_local_contact
1561 != NULL);
1562 sip_free_header(_dialog->
1563 sip_dlg_local_contact);
1564 _dialog->sip_dlg_local_contact =
1565 _dialog->sip_dlg_new_local_contact;
1566 _dialog->sip_dlg_new_local_contact =
1567 NULL;
1571 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1573 return (0);
1577 * Copy partial dialog to create a complete dialog
1579 _sip_dialog_t *
1580 sip_copy_partial_dialog(_sip_dialog_t *dialog)
1582 _sip_dialog_t *new_dlg;
1584 new_dlg = calloc(1, sizeof (_sip_dialog_t));
1585 if (new_dlg == NULL)
1586 return (NULL);
1587 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
1588 new_dlg->sip_dlg_req_uri.sip_str_ptr =
1589 malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);
1590 if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {
1591 free(new_dlg);
1592 return (NULL);
1594 (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,
1595 dialog->sip_dlg_req_uri.sip_str_ptr,
1596 dialog->sip_dlg_req_uri.sip_str_len);
1597 new_dlg->sip_dlg_req_uri.sip_str_ptr[
1598 dialog->sip_dlg_req_uri.sip_str_len] = '\0';
1599 new_dlg->sip_dlg_req_uri.sip_str_len =
1600 dialog->sip_dlg_req_uri.sip_str_len;
1602 if (dialog->sip_dlg_route_set != NULL) {
1603 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) {
1604 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1605 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1607 assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);
1608 new_dlg->sip_dlg_rset.sip_str_ptr =
1609 malloc(dialog->sip_dlg_rset.sip_str_len + 1);
1610 if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {
1611 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1612 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1613 free(new_dlg);
1614 return (NULL);
1616 (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,
1617 dialog->sip_dlg_rset.sip_str_ptr,
1618 dialog->sip_dlg_rset.sip_str_len);
1619 new_dlg->sip_dlg_rset.sip_str_ptr[
1620 dialog->sip_dlg_rset.sip_str_len] = '\0';
1621 new_dlg->sip_dlg_rset.sip_str_len =
1622 dialog->sip_dlg_rset.sip_str_len;
1624 new_dlg->sip_dlg_route_set =
1625 sip_dup_header(dialog->sip_dlg_route_set);
1626 if (new_dlg->sip_dlg_route_set == NULL) {
1627 free(new_dlg->sip_dlg_rset.sip_str_ptr);
1628 if (new_dlg->sip_dlg_req_uri.sip_str_ptr != NULL)
1629 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1630 free(new_dlg);
1631 return (NULL);
1634 if ((new_dlg->sip_dlg_local_uri_tag =
1635 sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||
1636 (new_dlg->sip_dlg_remote_target =
1637 sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||
1638 (new_dlg->sip_dlg_local_contact =
1639 sip_dup_header(dialog->sip_dlg_local_contact)) == NULL ||
1640 (new_dlg->sip_dlg_call_id =
1641 sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
1642 sip_release_dialog_res(new_dlg);
1643 return (NULL);
1645 if (dialog->sip_dlg_event != NULL) {
1646 new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);
1647 if (new_dlg->sip_dlg_event == NULL) {
1648 sip_release_dialog_res(new_dlg);
1649 return (NULL);
1652 new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;
1653 new_dlg->sip_dlg_type = dialog->sip_dlg_type;
1654 new_dlg->sip_dlg_on_fork = B_FALSE;
1655 (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);
1657 return (new_dlg);
1661 * Update the dialog using the response
1663 sip_dialog_t
1664 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1666 _sip_dialog_t *_dialog;
1667 boolean_t isreq;
1668 sip_method_t method;
1669 int resp_code = 0;
1670 int prev_state;
1671 boolean_t decr_ref = B_FALSE;
1672 int error;
1674 _dialog = (_sip_dialog_t *)dialog;
1675 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1676 _dialog->sip_dlg_msgcnt++;
1677 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1678 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1679 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1681 isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1682 if (error != 0)
1683 return (dialog);
1684 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1685 if (isreq) {
1686 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
1687 if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||
1688 method != NOTIFY) {
1689 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1690 return (dialog);
1692 } else {
1693 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1694 if (error != 0) {
1695 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1696 return (dialog);
1698 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1699 if (error != 0) {
1700 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1701 return (dialog);
1704 prev_state = _dialog->sip_dlg_state;
1705 if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {
1706 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1707 } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1709 * Let the user delete the dialog if it is not a 1XX/2XX resp
1710 * for an early dialog.
1712 if (isreq) {
1713 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1714 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1716 assert(!isreq);
1717 if (SIP_OK_RESP(resp_code)) {
1718 _dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1720 * If we recieved provisional response before we would
1721 * not have captured local contact. So store it now.
1723 if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog->
1724 sip_dlg_method == INVITE && method == INVITE) {
1725 sip_header_t chdr;
1726 (void) pthread_mutex_lock(&sip_msg->
1727 sip_msg_mutex);
1728 chdr = sip_search_for_header(sip_msg,
1729 SIP_CONTACT, NULL);
1730 (void) pthread_mutex_unlock(&sip_msg->
1731 sip_msg_mutex);
1732 if (chdr != NULL) {
1733 _dialog->sip_dlg_local_contact
1734 = sip_dup_header(chdr);
1735 _dialog->sip_dlg_new_local_contact =
1736 NULL;
1739 (void) sip_dlg_recompute_rset(_dialog, sip_msg,
1740 SIP_UAS_DIALOG);
1741 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1742 if (sip_dlg_ulp_state_cb != NULL) {
1743 sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
1744 prev_state, dialog->sip_dlg_state);
1746 } else {
1747 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1749 } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {
1750 if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&
1751 SIP_PROVISIONAL_RESP(resp_code)) {
1752 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1753 return (dialog);
1755 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1756 _sip_dialog_t *new_dlg;
1758 if (_dialog->sip_dlg_on_fork) {
1759 new_dlg = sip_copy_partial_dialog(_dialog);
1760 if (new_dlg == NULL) {
1761 (void) pthread_mutex_unlock(
1762 &_dialog->sip_dlg_mutex);
1763 return (dialog);
1766 * This decr/incr dance is because the caller
1767 * has incremented the ref on the partial
1768 * dialog, we release it here and incr the
1769 * ref on the new dialog which will be
1770 * released by the caller.
1772 (void) pthread_mutex_unlock(
1773 &_dialog->sip_dlg_mutex);
1774 SIP_DLG_REFCNT_DECR(_dialog);
1775 _dialog = new_dlg;
1776 (void) pthread_mutex_lock(
1777 &_dialog->sip_dlg_mutex);
1778 SIP_DLG_REFCNT_INCR(_dialog);
1779 } else {
1780 int index;
1783 * take it out of the list so that further
1784 * responses will not result in a dialog.
1785 * We will have an extra refcount when we
1786 * come back from sip_complete_dialog(), i.e.
1787 * one when the partial dialog was created -
1788 * in sip_seed_dialog(), one held by the caller
1789 * and one that will be added by
1790 * sip_complete_dialog(). We need to release
1791 * the one added by the sip_seed_dialog(),
1792 * since the one in sip_complete_dialog()
1793 * is for the same purpose.
1795 if (SIP_IS_TIMER_RUNNING(
1796 _dialog->sip_dlg_timer)) {
1797 SIP_CANCEL_TIMER(
1798 _dialog->sip_dlg_timer);
1800 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1801 (void) pthread_mutex_unlock(
1802 &_dialog->sip_dlg_mutex);
1803 sip_hash_delete(sip_dialog_phash,
1804 (void *)_dialog->sip_dlg_id,
1805 index, sip_dialog_dontfree);
1806 (void) pthread_mutex_lock(
1807 &_dialog->sip_dlg_mutex);
1808 decr_ref = B_TRUE;
1810 } else {
1811 decr_ref = B_TRUE;
1813 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1814 if ((dialog = sip_complete_dialog(sip_msg, _dialog)) ==
1815 NULL) {
1816 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref)
1817 SIP_DLG_REFCNT_DECR(_dialog);
1818 return (NULL);
1820 if (decr_ref)
1821 SIP_DLG_REFCNT_DECR(_dialog);
1822 } else {
1823 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1825 return (dialog);
1829 * Initialize the hash table
1831 void
1832 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
1833 void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int))
1835 int cnt;
1837 for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
1838 sip_dialog_hash[cnt].hash_count = 0;
1839 sip_dialog_hash[cnt].hash_head = NULL;
1840 sip_dialog_hash[cnt].hash_tail = NULL;
1841 (void) pthread_mutex_init(
1842 &sip_dialog_hash[cnt].sip_hash_mutex, NULL);
1843 sip_dialog_phash[cnt].hash_count = 0;
1844 sip_dialog_phash[cnt].hash_head = NULL;
1845 sip_dialog_phash[cnt].hash_tail = NULL;
1846 (void) pthread_mutex_init(
1847 &sip_dialog_phash[cnt].sip_hash_mutex, NULL);
1849 if (ulp_dlg_del != NULL)
1850 sip_ulp_dlg_del_cb = ulp_dlg_del;
1852 if (ulp_state_cb != NULL)
1853 sip_dlg_ulp_state_cb = ulp_state_cb;
1857 * Copy the new contact header of re-INVITE
1859 void
1860 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1862 sip_header_t chdr = NULL;
1863 sip_header_t nhdr = NULL;
1865 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1866 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1867 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1869 if (chdr == NULL)
1870 return;
1872 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1873 if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state
1874 != SIP_DLG_CONFIRMED) {
1875 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1876 return;
1879 if (((nhdr = sip_dup_header(chdr)) != NULL)) {
1880 if (dialog->sip_dlg_new_local_contact != NULL)
1881 sip_free_header(dialog->sip_dlg_new_local_contact);
1882 dialog->sip_dlg_new_local_contact = nhdr;
1884 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1888 * Given a state, return the string - This is mostly for debug purposes
1890 char *
1891 sip_get_dialog_state_str(int state)
1893 switch (state) {
1894 case SIP_DLG_NEW:
1895 return ("SIP_DLG_NEW");
1896 case SIP_DLG_EARLY:
1897 return ("SIP_DLG_EARLY");
1898 case SIP_DLG_CONFIRMED:
1899 return ("SIP_DLG_CONFIRMED");
1900 case SIP_DLG_DESTROYED:
1901 return ("SIP_DLG_DESTROYED");
1902 default:
1903 return ("UNKNOWN");