libc: make stdio_impl.h an internal libc header
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_dialog.c
blob5c3f3ac2a76e43ecc3cacb3e5993a937c7ed7a3c
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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <errno.h>
31 #include <pthread.h>
32 #include <strings.h>
33 #include <sip.h>
35 #include "sip_msg.h"
36 #include "sip_miscdefs.h"
37 #include "sip_hash.h"
38 #include "sip_dialog.h"
39 #include "sip_parse_generic.h"
41 #define SIP_DLG_XCHG_FROM 0
42 #define SIP_DLG_XCHG_TO 1
45 * Dialog state change callback function
47 void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;
48 void (*sip_ulp_dlg_del_cb)(sip_dialog_t, sip_msg_t, void *) = NULL;
50 boolean_t sip_incomplete_dialog(sip_dialog_t);
53 * Exchange From/To header
55 _sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);
58 * Complete dialog hash table
60 sip_hash_t sip_dialog_hash[SIP_HASH_SZ];
63 * Partial dialog hash table
65 sip_hash_t sip_dialog_phash[SIP_HASH_SZ];
68 * Route set structure
70 typedef struct sip_dlg_route_set_s {
71 char *sip_dlg_route;
72 sip_str_t sip_dlg_ruri;
73 boolean_t sip_dlg_route_lr;
74 struct sip_dlg_route_set_s *sip_dlg_route_next;
75 }sip_dlg_route_set_t;
77 sip_dialog_t sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,
78 boolean_t, int);
79 sip_dialog_t sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *);
80 int sip_dialog_process(_sip_msg_t *, sip_dialog_t *);
81 void sip_dialog_delete(_sip_dialog_t *);
82 void sip_dialog_init();
83 sip_dialog_t sip_dialog_find(_sip_msg_t *);
84 boolean_t sip_dialog_match(void *, void *);
85 boolean_t sip_dialog_free(void *, void *, int *);
86 sip_dialog_t sip_update_dialog(sip_dialog_t, _sip_msg_t *);
87 char *sip_dialog_req_uri(sip_dialog_t);
89 static void sip_release_dialog_res(_sip_dialog_t *);
90 void sip_dlg_self_destruct(void *);
91 static int sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,
92 int);
93 static void sip_dialog_free_rset(sip_dlg_route_set_t *);
96 * Timer object for partial dialogs
98 typedef struct sip_dialog_timer_obj_s {
99 _sip_dialog_t *dialog;
100 void (*func)(sip_dialog_t, sip_msg_t, void *);
101 } sip_dialog_timer_obj_t;
104 * To avoid duplication all over the place
106 static void
107 sip_release_dialog_res(_sip_dialog_t *dialog)
109 int count = 0;
110 sip_msg_chain_t *msg_chain;
111 sip_msg_chain_t *nmsg_chain;
113 if (dialog->sip_dlg_ref_cnt != 0) {
114 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
115 SIP_ASSERT_ERROR, __FILE__, __LINE__);
117 assert(dialog->sip_dlg_ref_cnt == 0);
118 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
119 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
120 if (dialog->sip_dlg_call_id != NULL)
121 sip_free_header(dialog->sip_dlg_call_id);
122 if (dialog->sip_dlg_local_uri_tag != NULL)
123 sip_free_header(dialog->sip_dlg_local_uri_tag);
124 if (dialog->sip_dlg_remote_uri_tag != NULL)
125 sip_free_header(dialog->sip_dlg_remote_uri_tag);
126 if (dialog->sip_dlg_remote_target != NULL)
127 sip_free_header(dialog->sip_dlg_remote_target);
128 if (dialog->sip_dlg_local_contact != NULL)
129 sip_free_header(dialog->sip_dlg_local_contact);
130 if (dialog->sip_dlg_new_local_contact != NULL)
131 sip_free_header(dialog->sip_dlg_new_local_contact);
132 if (dialog->sip_dlg_route_set != NULL)
133 sip_free_header(dialog->sip_dlg_route_set);
134 if (dialog->sip_dlg_event != NULL)
135 sip_free_header(dialog->sip_dlg_event);
136 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
137 free(dialog->sip_dlg_req_uri.sip_str_ptr);
138 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
139 dialog->sip_dlg_req_uri.sip_str_len = 0;
141 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
142 free(dialog->sip_dlg_rset.sip_str_ptr);
143 dialog->sip_dlg_rset.sip_str_len = 0;
144 dialog->sip_dlg_rset.sip_str_ptr = NULL;
146 for (count = 0; count <= SIP_DLG_DESTROYED; count++) {
147 msg_chain = dialog->sip_dlg_log[count].sip_msgs;
148 while (msg_chain != NULL) {
149 nmsg_chain = msg_chain->next;
150 free(msg_chain->sip_msg);
151 free(msg_chain);
152 msg_chain = nmsg_chain;
155 (void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);
156 free(dialog);
160 * Get the route information from the 'value' and add it to the route
161 * set.
163 static sip_dlg_route_set_t *
164 sip_add_route_to_set(sip_hdr_value_t *value)
166 int vlen = 0;
167 sip_dlg_route_set_t *rset;
168 char *crlf;
169 const sip_param_t *uri_param;
170 int error;
172 rset = calloc(1, sizeof (*rset));
173 if (rset == NULL)
174 return (NULL);
175 rset->sip_dlg_route_next = NULL;
176 vlen = value->sip_value_end - value->sip_value_start;
179 * check for CRLF
181 crlf = value->sip_value_end - strlen(SIP_CRLF);
182 while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
183 vlen -= strlen(SIP_CRLF);
184 crlf -= strlen(SIP_CRLF);
186 rset->sip_dlg_route = calloc(1, vlen + 1);
187 if (rset->sip_dlg_route == NULL) {
188 free(rset);
189 return (NULL);
192 * loose routing
194 rset->sip_dlg_route_lr = B_FALSE;
195 (void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);
196 rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +
197 (value->cftr_uri.sip_str_ptr - value->sip_value_start);
198 rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;
199 rset->sip_dlg_route[vlen] = '\0';
201 assert(value->sip_value_parsed_uri != NULL);
203 * Check if the 'lr' param is present for this route.
205 uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);
206 if (error != 0) {
207 free(rset->sip_dlg_route);
208 free(rset);
209 return (NULL);
211 if (uri_param != NULL) {
212 rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",
213 strlen("lr"));
215 return (rset);
219 * Depending on the route-set, determine the request URI.
221 char *
222 sip_dialog_req_uri(sip_dialog_t dialog)
224 const sip_str_t *req_uri;
225 char *uri;
226 _sip_dialog_t *_dialog;
228 _dialog = (_sip_dialog_t *)dialog;
229 if (_dialog->sip_dlg_route_set == NULL ||
230 _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
231 const struct sip_value *val;
233 val = sip_get_header_value(_dialog->sip_dlg_remote_target,
234 NULL);
235 if (val == NULL)
236 return (NULL);
237 req_uri = &((sip_hdr_value_t *)val)->cftr_uri;
238 } else {
239 req_uri = &_dialog->sip_dlg_req_uri;
241 uri = (char *)malloc(req_uri->sip_str_len + 1);
242 if (uri == NULL)
243 return (NULL);
244 (void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);
245 uri[req_uri->sip_str_len] = '\0';
247 return (uri);
251 * Free the route set.
253 void
254 sip_dialog_free_rset(sip_dlg_route_set_t *rset)
256 sip_dlg_route_set_t *next;
258 while (rset != NULL) {
259 next = rset->sip_dlg_route_next;
260 rset->sip_dlg_route_next = NULL;
261 free(rset->sip_dlg_route);
262 free(rset);
263 rset = next;
268 * Recompute route-set
270 static int
271 sip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
273 int ret;
275 if (dialog->sip_dlg_route_set != NULL) {
276 sip_free_header(dialog->sip_dlg_route_set);
277 dialog->sip_dlg_route_set = NULL;
279 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
280 free(dialog->sip_dlg_req_uri.sip_str_ptr);
281 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
282 dialog->sip_dlg_req_uri.sip_str_len = 0;
284 if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {
285 free(dialog->sip_dlg_rset.sip_str_ptr);
286 dialog->sip_dlg_rset.sip_str_ptr = NULL;
287 dialog->sip_dlg_rset.sip_str_len = 0;
289 ret = sip_dialog_get_route_set(dialog, sip_msg, what);
290 return (ret);
294 * If the route set is empty, the UAC MUST place the remote target URI
295 * into the Request-URI. The UAC MUST NOT add a Route header field to
296 * the request.
298 * If the route set is not empty, and the first URI in the route set
299 * contains the lr parameter (see Section 19.1.1), the UAC MUST place
300 * the remote target URI into the Request-URI and MUST include a Route
301 * header field containing the route set values in order, including all
302 * parameters.
304 * If the route set is not empty, and its first URI does not contain the
305 * lr parameter, the UAC MUST place the first URI from the route set
306 * into the Request-URI, stripping any parameters that are not allowed
307 * in a Request-URI. The UAC MUST add a Route header field containing
308 * the remainder of the route set values in order, including all
309 * parameters. The UAC MUST then place the remote target URI into the
310 * Route header field as the last value.
313 sip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,
314 int rcnt, int rlen)
316 size_t rset_len;
317 _sip_header_t *rhdr;
318 char *rset;
319 char *rp;
320 char *rsp;
321 int count;
322 sip_dlg_route_set_t *route;
323 boolean_t first = B_TRUE;
324 const sip_str_t *to_uri;
325 char *uri = NULL;
326 int rspl;
327 int rpl;
329 if (rcnt <= 0) {
330 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
331 SIP_ASSERT_ERROR, __FILE__, __LINE__);
333 assert(rcnt > 0);
335 dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;
336 dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);
337 if (dialog->sip_dlg_rset.sip_str_ptr == NULL)
338 return (ENOMEM);
339 rsp = dialog->sip_dlg_rset.sip_str_ptr;
340 rspl = rlen + rcnt;
341 route = rset_head;
342 rset_len = rlen;
343 if (!route->sip_dlg_route_lr) {
344 const struct sip_value *val;
346 val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);
347 to_uri = &((sip_hdr_value_t *)val)->cftr_uri;
348 uri = (char *)malloc(to_uri->sip_str_len + 1);
349 if (uri == NULL) {
350 free(dialog->sip_dlg_rset.sip_str_ptr);
351 dialog->sip_dlg_rset.sip_str_len = 0;
352 dialog->sip_dlg_rset.sip_str_ptr = NULL;
353 return (ENOMEM);
355 (void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);
356 uri[to_uri->sip_str_len] = '\0';
357 rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +
358 SIP_SPACE_LEN + sizeof (char) + SIP_SPACE_LEN +
359 sizeof (char);
360 count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);
361 dialog->sip_dlg_req_uri.sip_str_ptr = malloc(
362 route->sip_dlg_ruri.sip_str_len + 1);
363 if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {
364 free(uri);
365 free(dialog->sip_dlg_rset.sip_str_ptr);
366 dialog->sip_dlg_rset.sip_str_len = 0;
367 dialog->sip_dlg_rset.sip_str_ptr = NULL;
368 return (ENOMEM);
370 (void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +
371 (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),
372 route->sip_dlg_ruri.sip_str_len);
373 dialog->sip_dlg_req_uri.sip_str_ptr[
374 route->sip_dlg_ruri.sip_str_len] = '\0';
375 dialog->sip_dlg_req_uri.sip_str_len =
376 route->sip_dlg_ruri.sip_str_len;
378 rsp += count;
379 rspl -= count;
380 route = route->sip_dlg_route_next;
384 * rcnt - 1 is for the number of COMMAs
386 rset_len += strlen(SIP_ROUTE) + SIP_SPACE_LEN + sizeof (char) +
387 SIP_SPACE_LEN + rcnt - 1;
388 rset = malloc(rset_len + 1);
389 if (rset == NULL) {
390 free(dialog->sip_dlg_rset.sip_str_ptr);
391 dialog->sip_dlg_rset.sip_str_len = 0;
392 dialog->sip_dlg_rset.sip_str_ptr = NULL;
393 return (ENOMEM);
395 rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));
396 if (rhdr == NULL) {
397 free(rset);
398 free(dialog->sip_dlg_rset.sip_str_ptr);
399 dialog->sip_dlg_rset.sip_str_len = 0;
400 dialog->sip_dlg_rset.sip_str_ptr = NULL;
401 return (ENOMEM);
404 rp = rset;
405 rpl = rset_len + 1;
406 count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);
407 rp += count;
408 rpl -= count;
410 while (route != NULL) {
411 if (first) {
412 count = snprintf(rp, rpl, "%s", route->sip_dlg_route);
413 rp += count;
414 rpl -= count;
415 first = B_FALSE;
416 if (uri != NULL) {
417 count = snprintf(rsp, rspl, "%c%s",
418 SIP_COMMA, route->sip_dlg_route);
419 } else {
420 count = snprintf(rsp, rspl, "%s",
421 route->sip_dlg_route);
423 rsp += count;
424 rspl -= count;
425 } else {
426 count = snprintf(rp, rpl, "%c%s", SIP_COMMA,
427 route->sip_dlg_route);
428 rp += count;
429 rpl -= count;
430 count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,
431 route->sip_dlg_route);
432 rsp += count;
433 rspl -= count;
435 route = route->sip_dlg_route_next;
437 if (rsp > dialog->sip_dlg_rset.sip_str_ptr +
438 dialog->sip_dlg_rset.sip_str_len) {
439 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
440 SIP_ASSERT_ERROR, __FILE__, __LINE__);
442 assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +
443 dialog->sip_dlg_rset.sip_str_len);
444 dialog->sip_dlg_rset.sip_str_ptr[dialog->sip_dlg_rset.sip_str_len] =
445 '\0';
446 if (uri != NULL) {
447 if (first) {
448 count = snprintf(rp, rpl, "%c %s %c", SIP_LAQUOT,
449 uri, SIP_RAQUOT);
450 } else {
451 count = snprintf(rp, rpl, "%c%c %s %c", SIP_COMMA,
452 SIP_LAQUOT, uri, SIP_RAQUOT);
454 rp += count;
455 rpl -= count;
456 free(uri);
458 if (rp > rset + rset_len) {
459 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
460 SIP_ASSERT_ERROR, __FILE__, __LINE__);
462 assert(rp <= rset + rset_len);
463 (void) snprintf(rhdr->sip_hdr_start, rset_len + strlen(SIP_CRLF) + 1,
464 "%s%s", rset, SIP_CRLF);
465 free(rset);
466 dialog->sip_dlg_route_set = (sip_header_t)rhdr;
467 sip_dialog_free_rset(rset_head);
468 return (0);
472 * UAC Behavior
473 * The route set MUST be set to the list of URIs in the Record-Route
474 * header field from the response, taken in reverse order and preserving
475 * all URI parameters.
477 * UAS behavior
478 * The route set MUST be set to the list of URIs in the Record-Route
479 * header field from the request, taken in order and preserving all URI
480 * parameters.
482 static int
483 sip_dialog_get_route_set(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what)
485 sip_header_t rrhdr;
486 sip_hdr_value_t *value;
487 int error;
488 sip_dlg_route_set_t *rset_head = NULL;
489 sip_dlg_route_set_t *rset_tail = NULL;
490 sip_dlg_route_set_t *rset;
491 int rset_cnt = 0;
492 int rset_len = 0;
494 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
495 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, NULL);
496 while (rrhdr != NULL) {
497 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
498 value = (sip_hdr_value_t *)sip_get_header_value(rrhdr, &error);
499 while (value != NULL && error == 0) {
500 char *crlf;
502 if (value->sip_value_state == SIP_VALUE_BAD) {
503 value = (sip_hdr_value_t *)sip_get_next_value(
504 (sip_header_value_t)value, &error);
505 continue;
507 rset = sip_add_route_to_set(value);
508 if (rset == NULL)
509 goto r_error;
511 * Add one for COMMA
513 rset_cnt++;
514 rset_len += (value->sip_value_end -
515 value->sip_value_start);
517 * Check for CRLF
519 crlf = value->sip_value_end - strlen(SIP_CRLF);
520 while (crlf != NULL &&
521 strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {
522 rset_len -= strlen(SIP_CRLF);
523 crlf -= strlen(SIP_CRLF);
525 if (rset_head == NULL) {
526 if (rset_tail != NULL) {
527 sip_write_to_log((void *)dialog,
528 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
529 __FILE__, __LINE__);
531 assert(rset_tail == NULL);
532 rset_head = rset_tail = rset;
533 } else if (what == SIP_UAS_DIALOG) {
534 rset_tail->sip_dlg_route_next = rset;
535 rset_tail = rset;
536 } else if (what == SIP_UAC_DIALOG) {
537 rset->sip_dlg_route_next = rset_head;
538 rset_head = rset;
539 } else {
540 sip_write_to_log((void *)dialog,
541 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
542 __FILE__, __LINE__);
543 assert(0);
545 value = (sip_hdr_value_t *)sip_get_next_value(
546 (sip_header_value_t)value, &error);
548 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
549 rrhdr = sip_search_for_header(sip_msg, SIP_RECORD_ROUTE, rrhdr);
551 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
552 if (rset_cnt == 0)
553 return (0);
554 if (sip_dialog_set_route_hdr(dialog, rset_head, rset_cnt,
555 rset_len) != 0) {
556 goto r_error;
558 return (0);
559 r_error:
560 sip_dialog_free_rset(rset_head);
561 return (ENOMEM);
565 * UAS behavior:
566 * The remote sequence number MUST be set to the value of the sequence
567 * number in the CSeq header field of the request. The local sequence
568 * number MUST be empty. The call identifier component of the dialog ID
569 * MUST be set to the value of the Call-ID in the request. The local
570 * tag component of the dialog ID MUST be set to the tag in the To field
571 * in the response to the request (which always includes a tag), and the
572 * remote tag component of the dialog ID MUST be set to the tag from the
573 * From field in the request. A UAS MUST be prepared to receive a
574 * request without a tag in the From field, in which case the tag is
575 * considered to have a value of null.
576 * The remote URI MUST be set to the URI in the From field, and the
577 * local URI MUST be set to the URI in the To field.
578 * The remote target MUST be set to the URI from the Contact header field
579 * of the request.
581 * UAC behavior:
582 * The local sequence number MUST be set to the value of the sequence
583 * number in the CSeq header field of the request. The remote sequence
584 * number MUST be empty (it is established when the remote UA sends a
585 * request within the dialog). The call identifier component of the
586 * dialog ID MUST be set to the value of the Call-ID in the request.
587 * The local tag component of the dialog ID MUST be set to the tag in
588 * the From field in the request, and the remote tag component of the
589 * dialog ID MUST be set to the tag in the To field of the response. A
590 * UAC MUST be prepared to receive a response without a tag in the To
591 * field, in which case the tag is considered to have a value of null.
592 * The remote URI MUST be set to the URI in the To field, and the local
593 * URI MUST be set to the URI in the From field.
594 * The remote target MUST be set to the URI from the Contact header field
595 * of the response.
600 * This is the routine that seeds a dialog.
602 sip_dialog_t
603 sip_seed_dialog(sip_conn_object_t obj, _sip_msg_t *sip_msg,
604 boolean_t dlg_on_fork, int dlg_type)
606 _sip_dialog_t *dialog;
607 int cseq;
608 sip_header_t fhdr = NULL;
609 sip_header_t thdr = NULL;
610 sip_header_t chdr;
611 sip_header_t cihdr;
612 sip_header_t evhdr = NULL;
613 const struct sip_value *value;
614 sip_dialog_timer_obj_t *tim_obj = NULL;
615 const sip_str_t *callid;
616 sip_method_t method;
617 int timer1 = sip_timer_T1;
618 int error;
620 if (!sip_msg_is_request((sip_msg_t)sip_msg, &error))
621 return (NULL);
623 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
625 * Only INVITE and SUBSCRIBE supported
627 if (error != 0 || (method != INVITE && method != SUBSCRIBE))
628 return (NULL);
631 * A request outside of a dialog MUST NOT contain a To tag
633 if (sip_get_to_tag((sip_msg_t)sip_msg, NULL) != NULL)
634 return (NULL);
636 if (dlg_type == SIP_UAS_DIALOG) {
637 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
638 SIP_DLG_XCHG_FROM);
639 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
640 } else {
641 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
642 fhdr = sip_search_for_header(sip_msg, SIP_FROM, NULL);
644 cihdr = sip_search_for_header(sip_msg, SIP_CALL_ID, NULL);
645 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
646 if (method == SUBSCRIBE)
647 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
648 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
649 if ((fhdr == NULL && thdr == NULL) || cihdr == NULL || chdr == NULL ||
650 (method == SUBSCRIBE && evhdr == NULL)) {
651 if (thdr != NULL)
652 sip_free_header(thdr);
653 return (NULL);
657 * Sanity check since we just store the headers in the dialog
659 if (sip_get_from_tag((sip_msg_t)sip_msg, NULL) == NULL ||
660 sip_get_from_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
661 ((cseq = sip_get_callseq_num((sip_msg_t)sip_msg, NULL)) == -1) ||
662 (callid = sip_get_callid((sip_msg_t)sip_msg, NULL)) == NULL ||
663 sip_get_to_uri_str((sip_msg_t)sip_msg, NULL) == NULL ||
664 ((value = sip_get_header_value(chdr, NULL)) == NULL) ||
665 sip_get_contact_uri_str((sip_header_value_t)value, NULL) == NULL) {
666 if (thdr != NULL)
667 sip_free_header(thdr);
668 return (NULL);
671 tim_obj = calloc(1, sizeof (sip_dialog_timer_obj_t));
672 if (tim_obj == NULL) {
673 if (thdr != NULL)
674 sip_free_header(thdr);
675 return (NULL);
677 dialog = calloc(1, sizeof (_sip_dialog_t));
678 if (dialog == NULL) {
679 if (thdr != NULL)
680 sip_free_header(thdr);
681 return (NULL);
684 * We will take the TO header with the tag when we complete this
685 * dialog
687 if (dlg_type == SIP_UAS_DIALOG) {
688 dialog->sip_dlg_remote_uri_tag = thdr;
690 * We take the remote target from the incoming request on the
691 * UAS. For the UAC, we will take it from the response.
693 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) ==
694 NULL) {
695 goto dia_err;
697 } else {
698 if ((dialog->sip_dlg_local_uri_tag = sip_dup_header(fhdr)) ==
699 NULL) {
700 goto dia_err;
703 * We take the local contact from the originating request on
704 * UAC. For the UAS, we will take it from the response.
706 if ((dialog->sip_dlg_local_contact = sip_dup_header(chdr)) ==
707 NULL) {
708 goto dia_err;
709 } else {
710 dialog->sip_dlg_new_local_contact = NULL;
713 if ((dialog->sip_dlg_call_id = sip_dup_header(cihdr)) == NULL)
714 goto dia_err;
715 if (method == SUBSCRIBE) {
716 dialog->sip_dlg_event = sip_dup_header(evhdr);
717 if (dialog->sip_dlg_event == NULL) {
718 goto dia_err;
721 dialog->sip_dlg_rset.sip_str_ptr = NULL;
722 dialog->sip_dlg_rset.sip_str_len = 0;
723 dialog->sip_dlg_req_uri.sip_str_ptr = NULL;
724 dialog->sip_dlg_req_uri.sip_str_len = 0;
726 * Get the route set from the request, if present
728 if (dlg_type == SIP_UAS_DIALOG &&
729 sip_dialog_get_route_set(dialog, sip_msg, dlg_type) != 0) {
730 goto dia_err;
732 if (dlg_type == SIP_UAC_DIALOG)
733 dialog->sip_dlg_local_cseq = cseq;
734 else
735 dialog->sip_dlg_remote_cseq = cseq;
736 dialog->sip_dlg_type = dlg_type;
737 dialog->sip_dlg_on_fork = dlg_on_fork;
738 dialog->sip_dlg_method = method;
740 * Set the partial dialog timer with the INVITE timeout val
742 if (sip_conn_timer1 != NULL)
743 timer1 = sip_conn_timer1(obj);
744 SIP_INIT_TIMER(dialog->sip_dlg_timer, 64 * timer1);
745 tim_obj->dialog = dialog;
747 * Since at the client we never pass the partial dialog, we need not
748 * invoke the callback when the partial dialog self-destructs.
750 if (dlg_type == SIP_UAS_DIALOG)
751 tim_obj->func = sip_ulp_dlg_del_cb;
752 SIP_SCHED_TIMER(dialog->sip_dlg_timer, (void *)tim_obj,
753 sip_dlg_self_destruct);
754 if (!SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
755 goto dia_err;
756 (void) pthread_mutex_init(&dialog->sip_dlg_mutex, NULL);
758 if (dlg_type == SIP_UAC_DIALOG) {
759 const sip_str_t *local_tag;
761 local_tag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
762 if (local_tag == NULL) {
763 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
764 SIP_ASSERT_ERROR, __FILE__, __LINE__);
766 assert(local_tag != NULL);
767 sip_md5_hash(local_tag->sip_str_ptr, local_tag->sip_str_len,
768 callid->sip_str_ptr, callid->sip_str_len,
769 NULL, 0, NULL, 0, NULL, 0, NULL, 0,
770 (uchar_t *)dialog->sip_dlg_id);
774 * Add it to the partial hash table
776 if (sip_hash_add(sip_dialog_phash, (void *)dialog,
777 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
778 goto dia_err;
782 dialog->sip_dlg_msgcnt = 1;
783 sip_add_log(&dialog->sip_dlg_log[dialog->sip_dlg_state],
784 (sip_msg_t)sip_msg, dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
786 SIP_DLG_REFCNT_INCR(dialog);
787 return ((sip_dialog_t)dialog);
788 dia_err:
789 sip_release_dialog_res(dialog);
790 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
791 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
792 free(tim_obj);
793 return (NULL);
797 * When creating a dialog from a NOTIFY request, we need to get the FROM
798 * header for the dialog from the TO header of the NOTIFY.
800 _sip_header_t *
801 sip_dlg_xchg_from_to(sip_msg_t sip_msg, int what)
803 int len;
804 _sip_header_t *newhdr;
805 int cnt;
806 const struct sip_header *hdr;
807 int hdrsize;
808 int error;
810 hdr = sip_get_header(sip_msg, what == SIP_DLG_XCHG_FROM ? SIP_FROM :
811 SIP_TO, NULL, &error);
812 if (error != 0 || hdr == NULL)
813 return (NULL);
814 if (sip_parse_goto_values((_sip_header_t *)hdr) != 0)
815 return (NULL);
816 len = hdr->sip_hdr_end - hdr->sip_hdr_current;
817 if (what == SIP_DLG_XCHG_FROM) {
818 hdrsize = len + strlen(SIP_TO) + SIP_SPACE_LEN + sizeof (char) +
819 SIP_SPACE_LEN;
820 } else {
821 hdrsize = len + strlen(SIP_FROM) + SIP_SPACE_LEN +
822 sizeof (char) + SIP_SPACE_LEN;
824 newhdr = sip_new_header(hdrsize);
825 if (newhdr == NULL)
826 return (NULL);
827 if (what == SIP_DLG_XCHG_FROM) {
828 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
829 "%s %c ", SIP_TO, SIP_HCOLON);
830 } else {
831 cnt = snprintf(newhdr->sip_hdr_current, hdrsize + 1,
832 "%s %c ", SIP_FROM, SIP_HCOLON);
834 newhdr->sip_hdr_current += cnt;
835 (void) strncpy(newhdr->sip_hdr_current, hdr->sip_hdr_current, len);
836 newhdr->sip_hdr_current += len;
837 assert(newhdr->sip_hdr_current == newhdr->sip_hdr_end);
838 assert(hdr->sip_header_functions != NULL);
841 * FROM and TO have common parsing functions
843 newhdr->sip_header_functions = hdr->sip_header_functions;
844 newhdr->sip_hdr_current = newhdr->sip_hdr_start;
846 return (newhdr);
850 * This is the response that completes the dialog that was created
851 * in sip_seed_dialog().
853 sip_dialog_t
854 sip_complete_dialog(_sip_msg_t *sip_msg, _sip_dialog_t *dialog)
856 _sip_header_t *thdr;
857 _sip_header_t *evhdr = NULL;
858 _sip_header_t *substate = NULL;
859 sip_header_t chdr = NULL;
860 int resp_code;
861 const sip_str_t *ttag;
862 const sip_str_t *remtag;
863 const sip_str_t *callid;
864 const struct sip_value *val;
865 sip_method_t method;
866 int error = 0;
867 int prev_state;
868 boolean_t alloc_thdr = B_FALSE;
870 if (sip_msg_is_request((sip_msg_t)sip_msg, &error) && error == 0)
871 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
872 else
873 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
874 if (error != 0 || dialog == NULL ||
875 (sip_msg_is_request((sip_msg_t)sip_msg, &error) &&
876 (dialog->sip_dlg_method == INVITE || method != NOTIFY))) {
877 return (NULL);
879 if ((dialog->sip_dlg_type == SIP_UAC_DIALOG && method != NOTIFY &&
880 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
881 dialog->sip_dlg_local_cseq) ||
882 (dialog->sip_dlg_type == SIP_UAS_DIALOG && method != NOTIFY &&
883 sip_get_callseq_num((sip_msg_t)sip_msg, NULL) !=
884 dialog->sip_dlg_remote_cseq)) {
885 return (NULL);
887 if (method == NOTIFY) {
888 const sip_str_t *sstate;
890 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
891 SIP_DLG_XCHG_FROM);
892 if (thdr == NULL)
893 return (NULL);
894 alloc_thdr = B_TRUE;
895 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
896 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
897 if (chdr == NULL) {
898 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
899 sip_free_header(thdr);
900 return (NULL);
902 evhdr = sip_search_for_header(sip_msg, SIP_EVENT, NULL);
903 if (evhdr == NULL) {
904 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
905 sip_free_header(thdr);
906 return (NULL);
908 substate = sip_search_for_header(sip_msg,
909 SIP_SUBSCRIPTION_STATE, NULL);
910 if (substate == NULL) {
911 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
912 sip_free_header(thdr);
913 return (NULL);
915 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
916 sstate = sip_get_substate((sip_msg_t)sip_msg, &error);
917 if (sstate == NULL || error != 0) {
918 sip_free_header(thdr);
919 return (NULL);
921 if ((sstate->sip_str_len != strlen("pending") &&
922 sstate->sip_str_len != strlen("active")) ||
923 ((sstate->sip_str_len == strlen("pending") &&
924 strncasecmp(sstate->sip_str_ptr, "pending",
925 strlen("pending")) != 0) ||
926 (sstate->sip_str_len == strlen("active") &&
927 strncasecmp(sstate->sip_str_ptr, "active",
928 strlen("active")) != 0))) {
929 sip_free_header(thdr);
930 return (NULL);
932 ttag = sip_get_from_tag((sip_msg_t)sip_msg, NULL);
933 } else {
934 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
935 thdr = sip_dlg_xchg_from_to((sip_msg_t)sip_msg,
936 SIP_DLG_XCHG_TO);
937 alloc_thdr = B_TRUE;
938 } else {
939 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
940 thdr = sip_search_for_header(sip_msg, SIP_TO, NULL);
941 if (dialog->sip_dlg_remote_target == NULL) {
942 chdr = sip_search_for_header(sip_msg,
943 SIP_CONTACT, NULL);
945 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
947 if (thdr == NULL) {
948 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
949 return (NULL);
951 ttag = sip_get_to_tag((sip_msg_t)sip_msg, NULL);
953 if (ttag == NULL) {
954 if (alloc_thdr)
955 sip_free_header(thdr);
956 return (NULL);
958 prev_state = dialog->sip_dlg_state;
960 if (method == NOTIFY) {
961 int error;
962 const sip_str_t *dlg_id_val = NULL;
963 const sip_str_t *event;
964 const sip_str_t *id_val = NULL;
965 sip_header_value_t ev_val;
966 sip_hdr_value_t *dlg_ev_val = NULL;
968 event = sip_get_event((sip_msg_t)sip_msg, &error);
969 if (event == NULL || error != 0) {
970 sip_free_header(thdr);
971 return (NULL);
973 ev_val = (sip_header_value_t)sip_get_header_value(evhdr,
974 &error);
975 if (ev_val != NULL)
976 id_val = sip_get_param_value(ev_val, "id", &error);
977 if (error == 0) {
978 dlg_ev_val = (sip_hdr_value_t *)sip_get_header_value(
979 dialog->sip_dlg_event, &error);
981 if (dlg_ev_val == NULL || error != 0) {
982 sip_free_header(thdr);
983 return (NULL);
985 dlg_id_val = sip_get_param_value((sip_header_value_t)dlg_ev_val,
986 "id", &error);
987 if (error != 0 ||
988 dlg_ev_val->str_val_len != event->sip_str_len ||
989 strncmp(dlg_ev_val->str_val_ptr, event->sip_str_ptr,
990 event->sip_str_len != 0)) {
991 sip_free_header(thdr);
992 return (NULL);
994 if ((dlg_id_val == NULL && id_val != NULL) ||
995 (dlg_id_val != NULL && id_val == NULL)) {
996 sip_free_header(thdr);
997 return (NULL);
998 } else if (dlg_id_val != NULL && id_val != NULL) {
999 if (dlg_id_val->sip_str_len != id_val->sip_str_len ||
1000 strncasecmp(dlg_id_val->sip_str_ptr,
1001 id_val->sip_str_ptr, dlg_id_val->sip_str_len) !=
1002 0) {
1003 sip_free_header(thdr);
1004 return (NULL);
1007 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1008 dialog->sip_dlg_remote_uri_tag = thdr;
1009 if ((dialog->sip_dlg_remote_target =
1010 sip_dup_header(chdr)) == NULL) {
1011 sip_free_header(thdr);
1012 return (NULL);
1014 } else {
1015 dialog->sip_dlg_local_uri_tag = thdr;
1017 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1018 } else {
1019 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1020 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1021 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1022 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1023 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1025 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1026 if (dialog->sip_dlg_remote_target == NULL && chdr != NULL) {
1027 if (dialog->sip_dlg_type != SIP_UAC_DIALOG) {
1028 sip_write_to_log((void *)dialog,
1029 SIP_DIALOG_LOG | SIP_ASSERT_ERROR,
1030 __FILE__, __LINE__);
1032 assert(dialog->sip_dlg_type == SIP_UAC_DIALOG);
1033 if ((dialog->sip_dlg_remote_target =
1034 sip_dup_header(chdr)) == NULL) {
1035 (void) pthread_mutex_unlock(
1036 &dialog->sip_dlg_mutex);
1037 if (alloc_thdr)
1038 sip_free_header(thdr);
1039 goto terminate_new_dlg;
1041 if (sip_dialog_get_route_set(dialog, sip_msg,
1042 dialog->sip_dlg_type) != 0) {
1043 (void) pthread_mutex_unlock(
1044 &dialog->sip_dlg_mutex);
1045 if (alloc_thdr)
1046 sip_free_header(thdr);
1047 goto terminate_new_dlg;
1050 if (SIP_PROVISIONAL_RESP(resp_code)) {
1051 dialog->sip_dlg_state = SIP_DLG_EARLY;
1052 } else if (SIP_OK_RESP(resp_code)) {
1054 * Per 12.1 the UAS must include the contact header
1055 * for a dialog establishing response, so if we
1056 * don't find one, we terminate it.
1058 if (dialog->sip_dlg_remote_target == NULL) {
1059 (void) pthread_mutex_unlock(
1060 &dialog->sip_dlg_mutex);
1061 if (sip_ulp_dlg_del_cb != NULL) {
1062 sip_ulp_dlg_del_cb(dialog,
1063 (sip_msg_t)sip_msg, NULL);
1065 if (alloc_thdr)
1066 sip_free_header(thdr);
1067 goto terminate_new_dlg;
1069 dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1070 } else {
1071 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1072 if (sip_ulp_dlg_del_cb != NULL) {
1073 sip_ulp_dlg_del_cb(dialog, (sip_msg_t)sip_msg,
1074 NULL);
1076 if (alloc_thdr)
1077 sip_free_header(thdr);
1078 goto terminate_new_dlg;
1080 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1081 dialog->sip_dlg_local_uri_tag = thdr;
1082 } else {
1083 if ((dialog->sip_dlg_remote_uri_tag =
1084 sip_dup_header(thdr)) == NULL) {
1085 (void) pthread_mutex_unlock(
1086 &dialog->sip_dlg_mutex);
1087 goto terminate_new_dlg;
1093 * We take the local contact for UAS Dialog from the response (either
1094 * NOTIFY for SUBSCRIBE request or from final response 2xx to INVITE
1095 * request)
1097 if ((dialog->sip_dlg_type == SIP_UAS_DIALOG) && (dialog->sip_dlg_state
1098 == SIP_DLG_CONFIRMED)) {
1099 if (chdr == NULL) {
1100 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1101 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1102 NULL);
1103 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1105 if ((chdr == NULL) || ((dialog->sip_dlg_local_contact =
1106 sip_dup_header(chdr)) == NULL)) {
1107 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1108 if (alloc_thdr)
1109 sip_free_header(thdr);
1110 goto terminate_new_dlg;
1115 * Cancel the partial dialog timer
1117 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1118 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1120 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1121 val = sip_get_header_value(dialog->sip_dlg_local_uri_tag,
1122 &error);
1123 } else {
1124 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
1125 &error);
1127 if (val == NULL || error != 0) {
1128 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1129 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1131 assert(val != NULL && error == 0);
1132 remtag = sip_get_param_value((sip_header_value_t)val, "tag", &error);
1134 val = sip_get_header_value(dialog->sip_dlg_call_id, &error);
1135 callid = &((sip_hdr_value_t *)val)->str_val;
1138 * Get an ID for this dialog
1140 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1141 sip_md5_hash(remtag->sip_str_ptr, remtag->sip_str_len,
1142 ttag->sip_str_ptr, ttag->sip_str_len,
1143 callid->sip_str_ptr, callid->sip_str_len,
1144 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1145 } else {
1146 sip_md5_hash(ttag->sip_str_ptr, ttag->sip_str_len,
1147 remtag->sip_str_ptr, remtag->sip_str_len,
1148 callid->sip_str_ptr, callid->sip_str_len,
1149 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)dialog->sip_dlg_id);
1152 SIP_DLG_REFCNT_INCR(dialog);
1153 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1156 * Add it to the hash table
1158 if (sip_hash_add(sip_dialog_hash, (void *)dialog,
1159 SIP_DIGEST_TO_HASH(dialog->sip_dlg_id)) != 0) {
1160 terminate_new_dlg:
1162 * So that sip_dialog_delete() does not try to remove
1163 * this from the hash table.
1165 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1166 if (dialog->sip_dlg_type == SIP_UAS_DIALOG) {
1167 if (dialog->sip_dlg_local_uri_tag != NULL) {
1168 sip_free_header(dialog->sip_dlg_local_uri_tag);
1169 dialog->sip_dlg_local_uri_tag = NULL;
1171 } else {
1172 if (dialog->sip_dlg_remote_uri_tag != NULL) {
1173 sip_free_header(dialog->sip_dlg_remote_uri_tag);
1174 dialog->sip_dlg_remote_uri_tag = NULL;
1177 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1178 sip_dialog_terminate(dialog, (sip_msg_t)sip_msg);
1179 return (NULL);
1181 if (sip_dlg_ulp_state_cb != NULL) {
1182 sip_dlg_ulp_state_cb((sip_dialog_t)dialog,
1183 (sip_msg_t)sip_msg, prev_state, dialog->sip_dlg_state);
1185 return ((sip_dialog_t)dialog);
1189 * Check if this dialog is a match.
1191 boolean_t
1192 sip_dialog_match(void *obj, void *hindex)
1194 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1196 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1197 if (dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1198 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1199 return (B_FALSE);
1201 if (bcmp(dialog->sip_dlg_id, hindex,
1202 sizeof (dialog->sip_dlg_id)) == 0) {
1203 SIP_DLG_REFCNT_INCR(dialog);
1204 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1205 return (B_TRUE);
1207 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1208 return (B_FALSE);
1212 * Don't delete, just take it out of the hash
1214 boolean_t
1215 sip_dialog_dontfree(void *obj, void *hindex, int *found)
1217 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1219 *found = 0;
1220 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1221 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1222 == 0) {
1223 *found = 1;
1224 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1225 return (B_TRUE);
1227 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1228 return (B_FALSE);
1232 * Free resources associated with the dialog, the object will be removed
1233 * from the hash list by sip_hash_delete.
1235 boolean_t
1236 sip_dialog_free(void *obj, void *hindex, int *found)
1238 _sip_dialog_t *dialog = (_sip_dialog_t *)obj;
1240 *found = 0;
1241 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1242 if (bcmp(dialog->sip_dlg_id, hindex, sizeof (dialog->sip_dlg_id))
1243 == 0) {
1244 *found = 1;
1245 if (dialog->sip_dlg_state != SIP_DLG_DESTROYED) {
1246 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1247 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1249 assert(dialog->sip_dlg_state == SIP_DLG_DESTROYED);
1250 if (dialog->sip_dlg_ref_cnt != 0) {
1251 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1252 return (B_FALSE);
1254 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1255 sip_release_dialog_res(dialog);
1256 return (B_TRUE);
1258 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1259 return (B_FALSE);
1263 * The UAS will receive the request from the transaction layer. If the
1264 * request has a tag in the To header field, the UAS core computes the
1265 * dialog identifier corresponding to the request and compares it with
1266 * existing dialogs. If there is a match, this is a mid-dialog request.
1268 sip_dialog_t
1269 sip_dialog_find(_sip_msg_t *sip_msg)
1271 const sip_str_t *localtag;
1272 const sip_str_t *remtag;
1273 const sip_str_t *callid;
1274 uint16_t digest[8];
1275 _sip_dialog_t *dialog;
1276 boolean_t is_request;
1277 int error;
1279 is_request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1280 if (error != 0)
1281 return (NULL);
1282 if (is_request) {
1283 localtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1284 if (error == 0)
1285 remtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1286 } else {
1287 remtag = sip_get_to_tag((sip_msg_t)sip_msg, &error);
1288 if (error == 0)
1289 localtag = sip_get_from_tag((sip_msg_t)sip_msg, &error);
1291 if (error != 0)
1292 return (NULL);
1293 callid = sip_get_callid((sip_msg_t)sip_msg, &error);
1294 if (error != 0 || remtag == NULL || localtag == NULL ||
1295 callid == NULL) {
1296 return (NULL);
1298 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1299 remtag->sip_str_ptr, remtag->sip_str_len,
1300 callid->sip_str_ptr, callid->sip_str_len,
1301 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1303 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_hash,
1304 (void *)digest, SIP_DIGEST_TO_HASH(digest), sip_dialog_match);
1305 if (dialog == NULL) {
1306 sip_md5_hash(localtag->sip_str_ptr, localtag->sip_str_len,
1307 NULL, 0, callid->sip_str_ptr, callid->sip_str_len,
1308 NULL, 0, NULL, 0, NULL, 0, (uchar_t *)digest);
1309 dialog = (_sip_dialog_t *)sip_hash_find(sip_dialog_phash,
1310 (void *)digest, SIP_DIGEST_TO_HASH(digest),
1311 sip_dialog_match);
1313 return ((sip_dialog_t)dialog);
1317 * We keep this partial dialog for the duration of the INVITE
1318 * transaction timeout duration, i.e. Timer B.
1320 void
1321 sip_dlg_self_destruct(void *args)
1323 sip_dialog_timer_obj_t *tim_obj = (sip_dialog_timer_obj_t *)args;
1324 _sip_dialog_t *dialog = (_sip_dialog_t *)tim_obj->dialog;
1325 int index;
1327 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1328 if (dialog->sip_dlg_state != SIP_DLG_NEW) {
1329 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1330 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1332 assert(dialog->sip_dlg_state == SIP_DLG_NEW);
1333 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1334 if (dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1335 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1336 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1337 sip_hash_delete(sip_dialog_phash, (void *)dialog->sip_dlg_id,
1338 index, sip_dialog_dontfree);
1339 } else {
1340 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1342 if (tim_obj->func != NULL)
1343 tim_obj->func(dialog, NULL, NULL);
1344 free(tim_obj);
1345 SIP_DLG_REFCNT_DECR(dialog);
1349 * Terminate a dialog
1351 void
1352 sip_dialog_terminate(_sip_dialog_t *dialog, sip_msg_t sip_msg)
1354 int prev_state;
1356 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1357 prev_state = dialog->sip_dlg_state;
1358 dialog->sip_dlg_state = SIP_DLG_DESTROYED;
1359 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1360 if (sip_dlg_ulp_state_cb != NULL) {
1361 sip_dlg_ulp_state_cb((sip_dialog_t)dialog, sip_msg, prev_state,
1362 dialog->sip_dlg_state);
1364 SIP_DLG_REFCNT_DECR(dialog);
1368 * Delete a dialog
1370 void
1371 sip_dialog_delete(_sip_dialog_t *dialog)
1373 int index;
1376 * partial dialog, not in the hash table
1378 if (dialog->sip_dlg_local_uri_tag == NULL ||
1379 dialog->sip_dlg_remote_uri_tag == NULL) {
1381 * Cancel the partial dialog timer
1383 if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))
1384 SIP_CANCEL_TIMER(dialog->sip_dlg_timer);
1385 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG, NULL, 0);
1386 sip_release_dialog_res(dialog);
1387 return;
1389 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1390 sip_hash_delete(sip_dialog_hash, (void *)dialog->sip_dlg_id, index,
1391 sip_dialog_free);
1395 * Get the remote target from the CONTACT header from the 200 OK response
1397 static boolean_t
1398 sip_get_rtarg(_sip_dialog_t *dialog, _sip_msg_t *sip_msg)
1400 sip_header_t chdr;
1402 if (dialog->sip_dlg_remote_target != NULL)
1403 return (B_TRUE);
1405 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1406 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1407 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1408 if (chdr == NULL)
1409 return (B_FALSE);
1410 if ((dialog->sip_dlg_remote_target = sip_dup_header(chdr)) == NULL)
1411 return (B_FALSE);
1413 return (B_TRUE);
1417 * Process an incoming request/response
1419 /* ARGSUSED */
1421 sip_dialog_process(_sip_msg_t *sip_msg, sip_dialog_t *sip_dialog)
1423 boolean_t request;
1424 _sip_dialog_t *_dialog;
1425 int error;
1427 _dialog = (_sip_dialog_t *)*sip_dialog;
1429 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1430 _dialog->sip_dlg_msgcnt++;
1431 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1432 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1433 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1435 request = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1436 if (error != 0)
1437 return (EINVAL);
1438 if (request) {
1439 uint32_t cseq;
1440 sip_method_t method;
1442 cseq = sip_get_callseq_num((sip_msg_t)sip_msg, &error);
1443 if (error != 0)
1444 return (EINVAL);
1445 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1446 if (error != 0)
1447 return (EINVAL);
1448 if (sip_get_request_method((sip_msg_t)sip_msg, &error) !=
1449 method) {
1450 return (EINVAL);
1452 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1454 * Requests that do not change in any way the state
1455 * of a dialog may be received within a dialog.
1456 * They are processed as if they had been received
1457 * outside the dialog.
1458 * For dialogs that have been established with an
1459 * INVITE, the only target refresh request defined is
1460 * re-INVITE.
1462 if (_dialog->sip_dlg_method == INVITE &&
1463 method == INVITE && _dialog->sip_dlg_remote_cseq != 0 &&
1464 SIP_CSEQ_LT(cseq, _dialog->sip_dlg_remote_cseq)) {
1465 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1466 return (EPROTO);
1469 * Target-Refresh request
1471 if (_dialog->sip_dlg_method == INVITE && method == INVITE) {
1472 sip_header_t chdr;
1473 sip_header_t nchdr;
1475 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1476 chdr = sip_search_for_header(sip_msg, SIP_CONTACT,
1477 NULL);
1478 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1479 if (chdr != NULL &&
1480 (nchdr = sip_dup_header(chdr)) != NULL) {
1481 if (_dialog->sip_dlg_remote_target != NULL) {
1482 sip_free_header(
1483 _dialog->sip_dlg_remote_target);
1485 _dialog->sip_dlg_remote_target = nchdr;
1488 _dialog->sip_dlg_remote_cseq = cseq;
1489 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1490 } else {
1491 int resp_code;
1492 sip_method_t method;
1493 int error;
1495 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1496 if (error == 0) {
1497 method = sip_get_callseq_method((sip_msg_t)sip_msg,
1498 &error);
1500 if (error != 0)
1501 return (error);
1503 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1504 if (_dialog->sip_dlg_state == SIP_DLG_DESTROYED) {
1505 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1506 return (0);
1508 if (_dialog->sip_dlg_state != SIP_DLG_EARLY &&
1509 _dialog->sip_dlg_state != SIP_DLG_CONFIRMED) {
1510 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1511 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1513 assert(_dialog->sip_dlg_state == SIP_DLG_EARLY ||
1514 _dialog->sip_dlg_state == SIP_DLG_CONFIRMED);
1516 * Let the user delete the dialog if it is not a 1XX/2XX resp
1517 * for an early INVITE dialog.
1519 if (SIP_OK_RESP(resp_code)) {
1520 if (method == INVITE) {
1521 if (!sip_get_rtarg(_dialog, sip_msg)) {
1522 (void) pthread_mutex_unlock(
1523 &_dialog->sip_dlg_mutex);
1524 if (sip_ulp_dlg_del_cb != NULL) {
1525 sip_ulp_dlg_del_cb(
1526 (sip_dialog_t)_dialog,
1527 (sip_msg_t)sip_msg, NULL);
1529 sip_dialog_terminate(_dialog,
1530 (sip_msg_t)sip_msg);
1531 return (0);
1533 if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1534 _dialog->sip_dlg_state =
1535 SIP_DLG_CONFIRMED;
1536 (void) sip_dlg_recompute_rset(_dialog,
1537 sip_msg, SIP_UAC_DIALOG);
1538 (void) pthread_mutex_unlock(
1539 &_dialog->sip_dlg_mutex);
1540 if (sip_dlg_ulp_state_cb != NULL) {
1541 sip_dlg_ulp_state_cb(
1542 (sip_dialog_t)_dialog,
1543 sip_msg, SIP_DLG_EARLY,
1544 _dialog->sip_dlg_state);
1546 return (0);
1547 } else if (_dialog->sip_dlg_new_local_contact
1548 != NULL) {
1549 if (_dialog->sip_dlg_local_contact ==
1550 NULL) {
1551 (void) sip_write_to_log((void *)
1552 _dialog, SIP_DIALOG_LOG |
1553 SIP_ASSERT_ERROR, __FILE__,
1554 __LINE__);
1556 assert(_dialog->sip_dlg_local_contact
1557 != NULL);
1558 sip_free_header(_dialog->
1559 sip_dlg_local_contact);
1560 _dialog->sip_dlg_local_contact =
1561 _dialog->sip_dlg_new_local_contact;
1562 _dialog->sip_dlg_new_local_contact =
1563 NULL;
1567 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1569 return (0);
1573 * Copy partial dialog to create a complete dialog
1575 _sip_dialog_t *
1576 sip_copy_partial_dialog(_sip_dialog_t *dialog)
1578 _sip_dialog_t *new_dlg;
1580 new_dlg = calloc(1, sizeof (_sip_dialog_t));
1581 if (new_dlg == NULL)
1582 return (NULL);
1583 if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {
1584 new_dlg->sip_dlg_req_uri.sip_str_ptr =
1585 malloc(dialog->sip_dlg_req_uri.sip_str_len + 1);
1586 if (new_dlg->sip_dlg_req_uri.sip_str_ptr == NULL) {
1587 free(new_dlg);
1588 return (NULL);
1590 (void) strncpy(new_dlg->sip_dlg_req_uri.sip_str_ptr,
1591 dialog->sip_dlg_req_uri.sip_str_ptr,
1592 dialog->sip_dlg_req_uri.sip_str_len);
1593 new_dlg->sip_dlg_req_uri.sip_str_ptr[
1594 dialog->sip_dlg_req_uri.sip_str_len] = '\0';
1595 new_dlg->sip_dlg_req_uri.sip_str_len =
1596 dialog->sip_dlg_req_uri.sip_str_len;
1598 if (dialog->sip_dlg_route_set != NULL) {
1599 if (dialog->sip_dlg_rset.sip_str_ptr == NULL) {
1600 sip_write_to_log((void *)dialog, SIP_DIALOG_LOG |
1601 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1603 assert(dialog->sip_dlg_rset.sip_str_ptr != NULL);
1604 new_dlg->sip_dlg_rset.sip_str_ptr =
1605 malloc(dialog->sip_dlg_rset.sip_str_len + 1);
1606 if (new_dlg->sip_dlg_rset.sip_str_ptr == NULL) {
1607 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1608 free(new_dlg);
1609 return (NULL);
1611 (void) strncpy(new_dlg->sip_dlg_rset.sip_str_ptr,
1612 dialog->sip_dlg_rset.sip_str_ptr,
1613 dialog->sip_dlg_rset.sip_str_len);
1614 new_dlg->sip_dlg_rset.sip_str_ptr[
1615 dialog->sip_dlg_rset.sip_str_len] = '\0';
1616 new_dlg->sip_dlg_rset.sip_str_len =
1617 dialog->sip_dlg_rset.sip_str_len;
1619 new_dlg->sip_dlg_route_set =
1620 sip_dup_header(dialog->sip_dlg_route_set);
1621 if (new_dlg->sip_dlg_route_set == NULL) {
1622 free(new_dlg->sip_dlg_rset.sip_str_ptr);
1623 free(new_dlg->sip_dlg_req_uri.sip_str_ptr);
1624 free(new_dlg);
1625 return (NULL);
1628 if ((new_dlg->sip_dlg_local_uri_tag =
1629 sip_dup_header(dialog->sip_dlg_local_uri_tag)) == NULL ||
1630 (new_dlg->sip_dlg_remote_target =
1631 sip_dup_header(dialog->sip_dlg_remote_target)) == NULL ||
1632 (new_dlg->sip_dlg_local_contact =
1633 sip_dup_header(dialog->sip_dlg_local_contact)) == NULL ||
1634 (new_dlg->sip_dlg_call_id =
1635 sip_dup_header(dialog->sip_dlg_call_id)) == NULL) {
1636 sip_release_dialog_res(new_dlg);
1637 return (NULL);
1639 if (dialog->sip_dlg_event != NULL) {
1640 new_dlg->sip_dlg_event = sip_dup_header(dialog->sip_dlg_event);
1641 if (new_dlg->sip_dlg_event == NULL) {
1642 sip_release_dialog_res(new_dlg);
1643 return (NULL);
1646 new_dlg->sip_dlg_local_cseq = dialog->sip_dlg_local_cseq;
1647 new_dlg->sip_dlg_type = dialog->sip_dlg_type;
1648 new_dlg->sip_dlg_on_fork = B_FALSE;
1649 (void) pthread_mutex_init(&new_dlg->sip_dlg_mutex, NULL);
1651 return (new_dlg);
1655 * Update the dialog using the response
1657 sip_dialog_t
1658 sip_update_dialog(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1660 _sip_dialog_t *_dialog;
1661 boolean_t isreq;
1662 sip_method_t method;
1663 int resp_code = 0;
1664 int prev_state;
1665 boolean_t decr_ref = B_FALSE;
1666 int error;
1668 _dialog = (_sip_dialog_t *)dialog;
1669 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1670 _dialog->sip_dlg_msgcnt++;
1671 sip_add_log(&_dialog->sip_dlg_log[_dialog->sip_dlg_state],
1672 (sip_msg_t)sip_msg, _dialog->sip_dlg_msgcnt, SIP_DIALOG_LOG);
1673 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1675 isreq = sip_msg_is_request((sip_msg_t)sip_msg, &error);
1676 if (error != 0)
1677 return (dialog);
1678 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
1679 if (isreq) {
1680 method = sip_get_request_method((sip_msg_t)sip_msg, &error);
1681 if (error != 0 || _dialog->sip_dlg_method != SUBSCRIBE ||
1682 method != NOTIFY) {
1683 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1684 return (dialog);
1686 } else {
1687 resp_code = sip_get_response_code((sip_msg_t)sip_msg, &error);
1688 if (error != 0) {
1689 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1690 return (dialog);
1692 method = sip_get_callseq_method((sip_msg_t)sip_msg, &error);
1693 if (error != 0) {
1694 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1695 return (dialog);
1698 prev_state = _dialog->sip_dlg_state;
1699 if (_dialog->sip_dlg_state == SIP_DLG_CONFIRMED) {
1700 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1701 } else if (_dialog->sip_dlg_state == SIP_DLG_EARLY) {
1703 * Let the user delete the dialog if it is not a 1XX/2XX resp
1704 * for an early dialog.
1706 if (isreq) {
1707 sip_write_to_log((void *)_dialog, SIP_DIALOG_LOG |
1708 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1710 assert(!isreq);
1711 if (SIP_OK_RESP(resp_code)) {
1712 _dialog->sip_dlg_state = SIP_DLG_CONFIRMED;
1714 * If we recieved provisional response before we would
1715 * not have captured local contact. So store it now.
1717 if (_dialog->sip_dlg_type == SIP_UAS_DIALOG && _dialog->
1718 sip_dlg_method == INVITE && method == INVITE) {
1719 sip_header_t chdr;
1720 (void) pthread_mutex_lock(&sip_msg->
1721 sip_msg_mutex);
1722 chdr = sip_search_for_header(sip_msg,
1723 SIP_CONTACT, NULL);
1724 (void) pthread_mutex_unlock(&sip_msg->
1725 sip_msg_mutex);
1726 if (chdr != NULL) {
1727 _dialog->sip_dlg_local_contact
1728 = sip_dup_header(chdr);
1729 _dialog->sip_dlg_new_local_contact =
1730 NULL;
1733 (void) sip_dlg_recompute_rset(_dialog, sip_msg,
1734 SIP_UAS_DIALOG);
1735 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1736 if (sip_dlg_ulp_state_cb != NULL) {
1737 sip_dlg_ulp_state_cb(dialog, (sip_msg_t)sip_msg,
1738 prev_state, dialog->sip_dlg_state);
1740 } else {
1741 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1743 } else if (_dialog->sip_dlg_state == SIP_DLG_NEW) {
1744 if (!isreq && _dialog->sip_dlg_method == SUBSCRIBE &&
1745 SIP_PROVISIONAL_RESP(resp_code)) {
1746 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1747 return (dialog);
1749 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG) {
1750 _sip_dialog_t *new_dlg;
1752 if (_dialog->sip_dlg_on_fork) {
1753 new_dlg = sip_copy_partial_dialog(_dialog);
1754 if (new_dlg == NULL) {
1755 (void) pthread_mutex_unlock(
1756 &_dialog->sip_dlg_mutex);
1757 return (dialog);
1760 * This decr/incr dance is because the caller
1761 * has incremented the ref on the partial
1762 * dialog, we release it here and incr the
1763 * ref on the new dialog which will be
1764 * released by the caller.
1766 (void) pthread_mutex_unlock(
1767 &_dialog->sip_dlg_mutex);
1768 SIP_DLG_REFCNT_DECR(_dialog);
1769 _dialog = new_dlg;
1770 (void) pthread_mutex_lock(
1771 &_dialog->sip_dlg_mutex);
1772 SIP_DLG_REFCNT_INCR(_dialog);
1773 } else {
1774 int index;
1777 * take it out of the list so that further
1778 * responses will not result in a dialog.
1779 * We will have an extra refcount when we
1780 * come back from sip_complete_dialog(), i.e.
1781 * one when the partial dialog was created -
1782 * in sip_seed_dialog(), one held by the caller
1783 * and one that will be added by
1784 * sip_complete_dialog(). We need to release
1785 * the one added by the sip_seed_dialog(),
1786 * since the one in sip_complete_dialog()
1787 * is for the same purpose.
1789 if (SIP_IS_TIMER_RUNNING(
1790 _dialog->sip_dlg_timer)) {
1791 SIP_CANCEL_TIMER(
1792 _dialog->sip_dlg_timer);
1794 index = SIP_DIGEST_TO_HASH(dialog->sip_dlg_id);
1795 (void) pthread_mutex_unlock(
1796 &_dialog->sip_dlg_mutex);
1797 sip_hash_delete(sip_dialog_phash,
1798 (void *)_dialog->sip_dlg_id,
1799 index, sip_dialog_dontfree);
1800 (void) pthread_mutex_lock(
1801 &_dialog->sip_dlg_mutex);
1802 decr_ref = B_TRUE;
1804 } else {
1805 decr_ref = B_TRUE;
1807 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1808 if ((dialog = sip_complete_dialog(sip_msg, _dialog)) ==
1809 NULL) {
1810 if (_dialog->sip_dlg_type == SIP_UAC_DIALOG && decr_ref)
1811 SIP_DLG_REFCNT_DECR(_dialog);
1812 return (NULL);
1814 if (decr_ref)
1815 SIP_DLG_REFCNT_DECR(_dialog);
1816 } else {
1817 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
1819 return (dialog);
1823 * Initialize the hash table
1825 void
1826 sip_dialog_init(void (*ulp_dlg_del) (sip_dialog_t, sip_msg_t, void *),
1827 void (*ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int))
1829 int cnt;
1831 for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
1832 sip_dialog_hash[cnt].hash_count = 0;
1833 sip_dialog_hash[cnt].hash_head = NULL;
1834 sip_dialog_hash[cnt].hash_tail = NULL;
1835 (void) pthread_mutex_init(
1836 &sip_dialog_hash[cnt].sip_hash_mutex, NULL);
1837 sip_dialog_phash[cnt].hash_count = 0;
1838 sip_dialog_phash[cnt].hash_head = NULL;
1839 sip_dialog_phash[cnt].hash_tail = NULL;
1840 (void) pthread_mutex_init(
1841 &sip_dialog_phash[cnt].sip_hash_mutex, NULL);
1843 if (ulp_dlg_del != NULL)
1844 sip_ulp_dlg_del_cb = ulp_dlg_del;
1846 if (ulp_state_cb != NULL)
1847 sip_dlg_ulp_state_cb = ulp_state_cb;
1851 * Copy the new contact header of re-INVITE
1853 void
1854 sip_dialog_add_new_contact(sip_dialog_t dialog, _sip_msg_t *sip_msg)
1856 sip_header_t chdr = NULL;
1857 sip_header_t nhdr = NULL;
1859 (void) pthread_mutex_lock(&sip_msg->sip_msg_mutex);
1860 chdr = sip_search_for_header(sip_msg, SIP_CONTACT, NULL);
1861 (void) pthread_mutex_unlock(&sip_msg->sip_msg_mutex);
1863 if (chdr == NULL)
1864 return;
1866 (void) pthread_mutex_lock(&dialog->sip_dlg_mutex);
1867 if (dialog->sip_dlg_method != INVITE || dialog->sip_dlg_state
1868 != SIP_DLG_CONFIRMED) {
1869 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1870 return;
1873 if (((nhdr = sip_dup_header(chdr)) != NULL)) {
1874 if (dialog->sip_dlg_new_local_contact != NULL)
1875 sip_free_header(dialog->sip_dlg_new_local_contact);
1876 dialog->sip_dlg_new_local_contact = nhdr;
1878 (void) pthread_mutex_unlock(&dialog->sip_dlg_mutex);
1882 * Given a state, return the string - This is mostly for debug purposes
1884 char *
1885 sip_get_dialog_state_str(int state)
1887 switch (state) {
1888 case SIP_DLG_NEW:
1889 return ("SIP_DLG_NEW");
1890 case SIP_DLG_EARLY:
1891 return ("SIP_DLG_EARLY");
1892 case SIP_DLG_CONFIRMED:
1893 return ("SIP_DLG_CONFIRMED");
1894 case SIP_DLG_DESTROYED:
1895 return ("SIP_DLG_DESTROYED");
1896 default:
1897 return ("UNKNOWN");