1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <pthread.h>
31 #include <sip.h>
32
33 #include "sip_msg.h"
34 #include "sip_miscdefs.h"
35 #include "sip_parse_uri.h"
36 #include "sip_dialog.h"
37
38 /*
39 * Create a request using the state maintained in the dialog.
40 */
41 sip_msg_t
sip_create_dialog_req(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)42 sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog,
43 char *transport, char *sent_by, int sent_by_port, char *via_param,
44 uint32_t maxforward, int cseq)
45 {
46 _sip_dialog_t *_dialog;
47 sip_msg_t sip_msg;
48 char *uri;
49 int oldseq = 0;
50
51 if (!sip_manage_dialog || dialog == NULL || transport == NULL ||
52 sent_by == NULL) {
53 return (NULL);
54 }
55 if ((sip_msg = sip_new_msg()) == NULL)
56 return (NULL);
57 _dialog = (_sip_dialog_t *)dialog;
58 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
59 /*
60 * Depending on the route set, if any, the request URI could either
61 * be the contact URI or the 1st URI from the route set.
62 */
63 uri = (char *)sip_dialog_req_uri(_dialog);
64 if (uri == NULL)
65 goto err_ret;
66 if (sip_add_request_line(sip_msg, method, uri) != 0) {
67 free(uri);
68 goto err_ret;
69 }
70 free(uri);
71 if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_uri_tag, NULL) != 0)
72 goto err_ret;
73 if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_uri_tag, NULL) !=
74 0) {
75 goto err_ret;
76 }
77 if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_contact, NULL) != 0)
78 goto err_ret;
79 if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
80 0) {
81 goto err_ret;
82 }
83 if (sip_add_maxforward(sip_msg, maxforward) != 0)
84 goto err_ret;
85 if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0)
86 goto err_ret;
87 if (cseq < 0) {
88 if (_dialog->sip_dlg_local_cseq == 0)
89 _dialog->sip_dlg_local_cseq = 1;
90 oldseq = _dialog->sip_dlg_local_cseq;
91 cseq = ++_dialog->sip_dlg_local_cseq;
92 }
93 if (sip_add_cseq(sip_msg, method, cseq) != 0) {
94 _dialog->sip_dlg_local_cseq = oldseq;
95 goto err_ret;
96 }
97 /*
98 * The route set, even if empty, overrides any pre-existing route set.
99 * If the route set is empty, the UAC MUST NOT add a Route header
100 * field to the request.
101 */
102 (void) sip_delete_header_by_name(sip_msg, SIP_ROUTE);
103
104 if (_dialog->sip_dlg_route_set != NULL) {
105 if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set,
106 NULL) != 0) {
107 _dialog->sip_dlg_local_cseq = oldseq;
108 goto err_ret;
109 }
110 }
111 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
112 return (sip_msg);
113 err_ret:
114 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
115 sip_free_msg(sip_msg);
116 return (NULL);
117 }
118
119 /*
120 * Create a request using the state maintained in the dialog. The request will
121 * not have Contact header.
122 */
123 sip_msg_t
sip_create_dialog_req_nocontact(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)124 sip_create_dialog_req_nocontact(sip_method_t method, sip_dialog_t dialog,
125 char *transport, char *sent_by, int sent_by_port, char *via_param,
126 uint32_t maxforward, int cseq)
127 {
128 sip_msg_t sip_msg;
129
130 sip_msg = sip_create_dialog_req(method, dialog, transport, sent_by,
131 sent_by_port, via_param, maxforward, cseq);
132 if (sip_msg != NULL) {
133 if (sip_delete_header_by_name(sip_msg, SIP_CONTACT) != 0) {
134 sip_free_msg(sip_msg);
135 return (NULL);
136 }
137 }
138
139 return (sip_msg);
140 }
141
142 /*
143 * Get the Dialog method
144 */
145 int
sip_get_dialog_method(sip_dialog_t dialog,int * error)146 sip_get_dialog_method(sip_dialog_t dialog, int *error)
147 {
148 _sip_dialog_t *_dialog;
149
150 if (error != NULL)
151 *error = 0;
152 if (!sip_manage_dialog) {
153 if (error != NULL)
154 *error = EINVAL;
155 return (0);
156 }
157 if (dialog == NULL) {
158 if (error != NULL)
159 *error = EINVAL;
160 return (0);
161 }
162 _dialog = (_sip_dialog_t *)dialog;
163 return (_dialog->sip_dlg_method);
164 }
165
166 /*
167 * Get the Dialog state
168 */
169 int
sip_get_dialog_state(sip_dialog_t dialog,int * error)170 sip_get_dialog_state(sip_dialog_t dialog, int *error)
171 {
172 _sip_dialog_t *_dialog;
173
174 if (error != NULL)
175 *error = 0;
176 if (!sip_manage_dialog) {
177 if (error != NULL)
178 *error = EINVAL;
179 return (0);
180 }
181 if (dialog == NULL) {
182 if (error != NULL)
183 *error = EINVAL;
184 return (0);
185 }
186 _dialog = (_sip_dialog_t *)dialog;
187 return (_dialog->sip_dlg_state);
188 }
189
190 /*
191 * Return the dialog callid
192 */
193 const sip_str_t *
sip_get_dialog_callid(sip_dialog_t dialog,int * error)194 sip_get_dialog_callid(sip_dialog_t dialog, int *error)
195 {
196 _sip_dialog_t *_dialog;
197 const struct sip_value *val;
198 const sip_str_t *callid = NULL;
199
200 if (error != NULL)
201 *error = 0;
202 if (!sip_manage_dialog || dialog == NULL) {
203 if (error != NULL)
204 *error = EINVAL;
205 return (NULL);
206 }
207 _dialog = (_sip_dialog_t *)dialog;
208 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
209 if (dialog->sip_dlg_call_id != NULL) {
210 val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
211 if (val == NULL) {
212 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
213 return (NULL);
214 }
215 callid = &((sip_hdr_value_t *)val)->str_val;
216 }
217 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
218 return (callid);
219 }
220
221 /*
222 * Return the dialog localtag.
223 */
224 const sip_str_t *
sip_get_dialog_local_tag(sip_dialog_t dialog,int * error)225 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
226 {
227 _sip_dialog_t *_dialog;
228 const sip_str_t *ltag = NULL;
229 const struct sip_value *val;
230
231 if (error != NULL)
232 *error = 0;
233 if (!sip_manage_dialog || dialog == NULL) {
234 if (error != NULL)
235 *error = EINVAL;
236 return (NULL);
237 }
238 _dialog = (_sip_dialog_t *)dialog;
239 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
240 if (dialog->sip_dlg_local_uri_tag != NULL) {
241 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
242 error);
243 if (val == NULL) {
244 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
245 return (NULL);
246 }
247 ltag = sip_get_param_value((sip_header_value_t)val, "tag",
248 error);
249 }
250 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
251 return (ltag);
252 }
253
254 /*
255 * Return the dialog remotetag
256 */
257 const sip_str_t *
sip_get_dialog_remote_tag(sip_dialog_t dialog,int * error)258 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
259 {
260 _sip_dialog_t *_dialog;
261 const sip_str_t *ttag = NULL;
262 const struct sip_value *val;
263
264 if (error != NULL)
265 *error = 0;
266 if (!sip_manage_dialog || dialog == NULL) {
267 if (error != NULL)
268 *error = EINVAL;
269 return (NULL);
270 }
271 _dialog = (_sip_dialog_t *)dialog;
272 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
273 if (dialog->sip_dlg_remote_uri_tag != NULL) {
274 val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
275 error);
276 if (val == NULL) {
277 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
278 return (NULL);
279 }
280 ttag = sip_get_param_value((sip_header_value_t)val, "tag",
281 error);
282 }
283 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
284
285 return (ttag);
286 }
287
288 /*
289 * Return the dialog localuri.
290 */
291 const struct sip_uri *
sip_get_dialog_local_uri(sip_dialog_t dialog,int * error)292 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
293 {
294 _sip_dialog_t *_dialog;
295 const _sip_uri_t *luri = NULL;
296 const struct sip_value *val;
297
298 if (error != NULL)
299 *error = 0;
300 if (!sip_manage_dialog || dialog == NULL) {
301 if (error != NULL)
302 *error = EINVAL;
303 return (NULL);
304 }
305 _dialog = (_sip_dialog_t *)dialog;
306 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
307 if (dialog->sip_dlg_local_uri_tag != NULL) {
308 val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
309 error);
310 if (val == NULL) {
311 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
312 return (NULL);
313 }
314 luri = val->sip_value_parse_uri;
315 }
316 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
317
318 return ((sip_uri_t)luri);
319 }
320
321 /*
322 * Return the dialog remoteuri.
323 */
324 const struct sip_uri *
sip_get_dialog_remote_uri(sip_dialog_t dialog,int * error)325 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
326 {
327 _sip_dialog_t *_dialog;
328 const _sip_uri_t *ruri = NULL;
329 const struct sip_value *val;
330
331 if (error != NULL)
332 *error = 0;
333 if (!sip_manage_dialog || dialog == NULL) {
334 if (error != NULL)
335 *error = EINVAL;
336 return (NULL);
337 }
338 _dialog = (_sip_dialog_t *)dialog;
339 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
340 if (dialog->sip_dlg_remote_uri_tag != NULL) {
341 val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
342 error);
343 if (val == NULL) {
344 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
345 return (NULL);
346 }
347 ruri = val->sip_value_parse_uri;
348 }
349 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
350 return ((sip_uri_t)ruri);
351 }
352
353 /*
354 * Return the dialog remotetarg.
355 */
356 const struct sip_uri *
sip_get_dialog_remote_target_uri(sip_dialog_t dialog,int * error)357 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
358 {
359 _sip_dialog_t *_dialog;
360 const struct sip_uri *rtarg = NULL;
361 const struct sip_value *val;
362
363 if (error != NULL)
364 *error = 0;
365 if (!sip_manage_dialog || dialog == NULL) {
366 if (error != NULL)
367 *error = EINVAL;
368 return (NULL);
369 }
370 _dialog = (_sip_dialog_t *)dialog;
371 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
372 if (dialog->sip_dlg_remote_target != NULL) {
373 val = sip_get_header_value(_dialog->sip_dlg_remote_target,
374 error);
375 if (val == NULL) {
376 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
377 return (NULL);
378 }
379 rtarg = val->sip_value_parse_uri;
380 }
381 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
382
383 return ((sip_uri_t)rtarg);
384 }
385
386 /*
387 * Return the dialog local contact uri.
388 */
389 const struct sip_uri *
sip_get_dialog_local_contact_uri(sip_dialog_t dialog,int * error)390 sip_get_dialog_local_contact_uri(sip_dialog_t dialog, int *error)
391 {
392 _sip_dialog_t *_dialog;
393 const struct sip_uri *lcuri = NULL;
394 const struct sip_value *val;
395
396 if (error != NULL)
397 *error = 0;
398 if (!sip_manage_dialog || dialog == NULL) {
399 if (error != NULL)
400 *error = EINVAL;
401 return (NULL);
402 }
403 _dialog = (_sip_dialog_t *)dialog;
404 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
405 if (dialog->sip_dlg_local_contact != NULL) {
406 val = sip_get_header_value(_dialog->sip_dlg_local_contact,
407 error);
408 if (val == NULL) {
409 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
410 return (NULL);
411 }
412 lcuri = val->sip_value_parse_uri;
413 }
414 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
415
416 return ((sip_uri_t)lcuri);
417 }
418
419 /*
420 * Return the dialog route set
421 */
422 const sip_str_t *
sip_get_dialog_route_set(sip_dialog_t dialog,int * error)423 sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
424 {
425 _sip_dialog_t *_dialog;
426
427 if (error != NULL)
428 *error = 0;
429 if (!sip_manage_dialog || dialog == NULL) {
430 if (error != NULL)
431 *error = EINVAL;
432 return (NULL);
433 }
434 _dialog = (_sip_dialog_t *)dialog;
435 if (_dialog->sip_dlg_rset.sip_str_len > 0)
436 return (&_dialog->sip_dlg_rset);
437 return (NULL);
438 }
439
440 /*
441 * Return the dialog secure
442 */
443 boolean_t
sip_is_dialog_secure(sip_dialog_t dialog,int * error)444 sip_is_dialog_secure(sip_dialog_t dialog, int *error)
445 {
446 _sip_dialog_t *_dialog;
447 boolean_t issecure;
448
449 if (error != NULL)
450 *error = 0;
451 if (!sip_manage_dialog || dialog == NULL) {
452 if (error != NULL)
453 *error = EINVAL;
454 return (B_FALSE);
455 }
456 _dialog = (_sip_dialog_t *)dialog;
457 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
458 issecure = _dialog->sip_dlg_secure;
459 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
460 return (issecure);
461 }
462
463 /*
464 * Return the dialog local cseq
465 */
466 uint32_t
sip_get_dialog_local_cseq(sip_dialog_t dialog,int * error)467 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
468 {
469 _sip_dialog_t *_dialog;
470 uint32_t cseq;
471
472 if (error != NULL)
473 *error = 0;
474 if (!sip_manage_dialog || dialog == NULL) {
475 if (error != NULL)
476 *error = EINVAL;
477 return (0);
478 }
479 _dialog = (_sip_dialog_t *)dialog;
480 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
481 cseq = _dialog->sip_dlg_local_cseq;
482 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
483 return (cseq);
484 }
485
486 /*
487 * Return the dialog remote cseq
488 */
489 uint32_t
sip_get_dialog_remote_cseq(sip_dialog_t dialog,int * error)490 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
491 {
492 _sip_dialog_t *_dialog;
493 uint32_t cseq;
494
495 if (error != NULL)
496 *error = 0;
497 if (!sip_manage_dialog || dialog == NULL) {
498 if (error != NULL)
499 *error = EINVAL;
500 return (0);
501 }
502 _dialog = (_sip_dialog_t *)dialog;
503 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
504 cseq = _dialog->sip_dlg_remote_cseq;
505 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
506 return (cseq);
507 }
508
509 /*
510 * Return the dialog type
511 */
512 int
sip_get_dialog_type(sip_dialog_t dialog,int * error)513 sip_get_dialog_type(sip_dialog_t dialog, int *error)
514 {
515 _sip_dialog_t *_dialog;
516 int type;
517
518 if (error != NULL)
519 *error = 0;
520 if (!sip_manage_dialog || dialog == NULL) {
521 if (error != NULL)
522 *error = EINVAL;
523 return (-1);
524 }
525 _dialog = (_sip_dialog_t *)dialog;
526 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
527 type = _dialog->sip_dlg_type;
528 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
529 return (type);
530 }
531
532 /*
533 * Return the number of messages exchanged within a dialog.
534 */
535 int
sip_get_dialog_msgcnt(sip_dialog_t dialog,int * error)536 sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
537 {
538 _sip_dialog_t *_dialog;
539 int nmsgs;
540
541 if (error != NULL)
542 *error = 0;
543 if (!sip_manage_dialog || dialog == NULL) {
544 if (error != NULL)
545 *error = EINVAL;
546 return (-1);
547 }
548 _dialog = (_sip_dialog_t *)dialog;
549 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
550 nmsgs = _dialog->sip_dlg_msgcnt;
551 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
552 return (nmsgs);
553 }
554
555 /*
556 * Partial dialog ?
557 */
558 boolean_t
sip_incomplete_dialog(sip_dialog_t dialog)559 sip_incomplete_dialog(sip_dialog_t dialog)
560 {
561 _sip_dialog_t *_dialog;
562 boolean_t isnew;
563
564 if (!sip_manage_dialog || dialog == NULL)
565 return (B_FALSE);
566 _dialog = (_sip_dialog_t *)dialog;
567 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
568 isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
569 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
570 return (isnew);
571 }
572
573 /*
574 * Hold dialog
575 */
576 void
sip_hold_dialog(sip_dialog_t dialog)577 sip_hold_dialog(sip_dialog_t dialog)
578 {
579 _sip_dialog_t *_dialog;
580
581 if (!sip_manage_dialog || dialog == NULL)
582 return;
583 _dialog = (_sip_dialog_t *)dialog;
584 (void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
585 SIP_DLG_REFCNT_INCR(_dialog);
586 (void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
587 }
588
589 /*
590 * Release dialog
591 */
592 void
sip_release_dialog(sip_dialog_t dialog)593 sip_release_dialog(sip_dialog_t dialog)
594 {
595 _sip_dialog_t *_dialog;
596
597 if (!sip_manage_dialog || dialog == NULL)
598 return;
599 _dialog = (_sip_dialog_t *)dialog;
600 SIP_DLG_REFCNT_DECR(_dialog);
601 }
602
603 /*
604 * Delete a dialog
605 */
606 void
sip_delete_dialog(sip_dialog_t dialog)607 sip_delete_dialog(sip_dialog_t dialog)
608 {
609 if (!sip_manage_dialog || dialog == NULL)
610 return;
611 sip_dialog_terminate(dialog, NULL);
612 }
613