8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_msg.c
blobf56ca4b70e5eda39c49168046ab9dee020644225
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 2007 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 <assert.h>
31 #include <errno.h>
32 #include <pthread.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sip.h>
37 #include "sip_msg.h"
38 #include "sip_miscdefs.h"
39 #include "sip_parse_generic.h"
42 * Response consists of SIP version, response code, response phrase and CRLF.
44 #define SIP_RESPONSE "%s %d %s%s"
46 void sip_free_content(_sip_msg_t *);
49 * Allocate a new sip msg struct.
51 sip_msg_t
52 sip_new_msg()
54 _sip_msg_t *sip_msg;
56 sip_msg = calloc(1, sizeof (_sip_msg_t));
57 if (sip_msg != NULL) {
58 sip_msg->sip_msg_ref_cnt = 1;
59 (void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
61 return ((sip_msg_t)sip_msg);
65 * Free all resources. The lock is taken by SIP_MSG_REFCNT_DECR. The
66 * thread that decrements the last refcount should take care that
67 * the message is not accessible to other threads before doing so.
68 * Else, if the message is still accessible to others, it is
69 * possible that the other thread could be waiting to take the
70 * lock when we proceed to destroy it.
72 void
73 sip_destroy_msg(_sip_msg_t *_sip_msg)
75 #ifdef __solaris__
76 assert(mutex_held(&_sip_msg->sip_msg_mutex));
77 #endif
78 (void) sip_delete_start_line_locked(_sip_msg);
79 assert(_sip_msg->sip_msg_ref_cnt == 0);
80 sip_delete_all_headers((sip_msg_t)_sip_msg);
81 sip_free_content(_sip_msg);
82 if (_sip_msg->sip_msg_buf != NULL)
83 free(_sip_msg->sip_msg_buf);
85 if (_sip_msg->sip_msg_old_buf != NULL)
86 free(_sip_msg->sip_msg_old_buf);
88 while (_sip_msg->sip_msg_req_res != NULL) {
89 sip_message_type_t *sip_msg_type_ptr;
91 sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
92 if (_sip_msg->sip_msg_req_res->is_request) {
93 sip_request_t *reqline;
95 reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
96 if (reqline->sip_parse_uri != NULL) {
97 sip_free_parsed_uri(reqline->sip_parse_uri);
98 reqline->sip_parse_uri = NULL;
101 free(_sip_msg->sip_msg_req_res);
102 _sip_msg->sip_msg_req_res = sip_msg_type_ptr;
104 (void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex);
105 free(_sip_msg);
109 * Free a sip msg struct.
111 void
112 sip_free_msg(sip_msg_t sip_msg)
114 if (sip_msg == NULL)
115 return;
117 SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg);
121 * Hold a sip msg struct.
123 void
124 sip_hold_msg(sip_msg_t sip_msg)
127 if (sip_msg == NULL)
128 return;
130 SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg);
134 * Clone a message
136 sip_msg_t
137 sip_clone_msg(sip_msg_t sip_msg)
139 _sip_msg_t *new_msg;
140 _sip_msg_t *_sip_msg;
141 sip_content_t *sip_content;
142 sip_content_t *msg_content;
143 sip_content_t *new_content = NULL;
144 int len;
146 if (sip_msg == NULL)
147 return (NULL);
148 new_msg = (_sip_msg_t *)sip_new_msg();
149 if (new_msg == NULL)
150 return (NULL);
151 _sip_msg = (_sip_msg_t *)sip_msg;
153 * Get start line
155 if (sip_copy_start_line(_sip_msg, new_msg) != 0) {
156 sip_free_msg((sip_msg_t)new_msg);
157 return (NULL);
159 if (sip_copy_all_headers(_sip_msg, new_msg) != 0) {
160 sip_free_msg((sip_msg_t)new_msg);
161 return (NULL);
163 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
164 sip_content = _sip_msg->sip_msg_content;
165 while (sip_content != NULL) {
166 msg_content = calloc(1, sizeof (sip_content_t));
167 if (msg_content == NULL) {
168 sip_free_msg((sip_msg_t)new_msg);
169 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
170 return (NULL);
172 len = sip_content->sip_content_end -
173 sip_content->sip_content_start;
174 msg_content->sip_content_start = malloc(len + 1);
175 if (msg_content->sip_content_start == NULL) {
176 sip_free_msg((sip_msg_t)new_msg);
177 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
178 return (NULL);
180 (void) strncpy(msg_content->sip_content_start,
181 sip_content->sip_content_start, len);
182 msg_content->sip_content_start[len] = '\0';
183 msg_content->sip_content_current =
184 msg_content->sip_content_start;
185 msg_content->sip_content_end = msg_content->sip_content_start +
186 len;
187 msg_content->sip_content_allocated = B_TRUE;
188 new_msg->sip_msg_content_len += len;
189 new_msg->sip_msg_len += len;
190 if (new_msg->sip_msg_content == NULL)
191 new_msg->sip_msg_content = msg_content;
192 else
193 new_content->sip_content_next = msg_content;
194 new_content = msg_content;
195 sip_content = sip_content->sip_content_next;
197 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
199 * Since this is a new message, no threads should be referring
200 * to this, so it is not necessary to take the lock, however,
201 * since sip_msg_to_msgbuf() expects the lock to be held, we'll
202 * take it here.
204 (void) pthread_mutex_lock(&new_msg->sip_msg_mutex);
205 new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
206 if (new_msg->sip_msg_buf == NULL) {
207 (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
208 sip_free_msg((sip_msg_t)new_msg);
209 return (NULL);
211 new_msg->sip_msg_cannot_be_modified = B_TRUE;
212 (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
214 return ((sip_msg_t)new_msg);
218 * Return the SIP message as a string. Caller frees the string
220 char *
221 sip_msg_to_str(sip_msg_t sip_msg, int *error)
223 _sip_msg_t *msg;
224 char *msgstr;
226 if (sip_msg == NULL) {
227 if (error != NULL)
228 *error = EINVAL;
229 return (NULL);
231 msg = (_sip_msg_t *)sip_msg;
232 (void) pthread_mutex_lock(&msg->sip_msg_mutex);
233 msgstr = sip_msg_to_msgbuf(msg, error);
234 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
235 return (msgstr);
239 * Given a message generate a string that includes all the headers and the
240 * content.
242 char *
243 sip_msg_to_msgbuf(_sip_msg_t *msg, int *error)
245 _sip_header_t *header;
246 int len = 0;
247 char *p;
248 char *e;
249 sip_content_t *sip_content;
250 #ifdef _DEBUG
251 int tlen = 0;
252 int clen = 0;
253 #endif
255 if (error != NULL)
256 *error = 0;
258 if (msg == NULL) {
259 if (error != NULL)
260 *error = EINVAL;
261 return (NULL);
263 #ifdef __solaris__
264 assert(mutex_held(&msg->sip_msg_mutex));
265 #endif
267 p = (char *)malloc(msg->sip_msg_len + 1);
268 if (p == NULL) {
269 if (error != 0)
270 *error = ENOMEM;
271 return (NULL);
273 e = p;
276 * Get the start line
278 if (msg->sip_msg_start_line != NULL) {
279 len = msg->sip_msg_start_line->sip_hdr_end -
280 msg->sip_msg_start_line->sip_hdr_start;
281 (void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
282 e += len;
283 #ifdef _DEBUG
284 tlen += len;
285 #endif
287 header = sip_search_for_header(msg, NULL, NULL);
288 while (header != NULL) {
289 if (header->sip_header_state != SIP_HEADER_DELETED) {
290 if (header->sip_header_state ==
291 SIP_HEADER_DELETED_VAL) {
292 len = sip_copy_values(e, header);
293 } else {
294 len = header->sip_hdr_end -
295 header->sip_hdr_start;
296 (void) strncpy(e, header->sip_hdr_start, len);
298 #ifdef _DEBUG
299 tlen += len;
300 assert(tlen <= msg->sip_msg_len);
301 #endif
303 header = sip_search_for_header(msg, NULL, header);
304 e += len;
306 sip_content = msg->sip_msg_content;
307 while (sip_content != NULL) {
308 len = sip_content->sip_content_end -
309 sip_content->sip_content_start;
310 #ifdef _DEBUG
311 clen += len;
312 assert(clen <= msg->sip_msg_content_len);
313 tlen += len;
314 assert(tlen <= msg->sip_msg_len);
315 #endif
316 (void) strncpy(e, sip_content->sip_content_start, len);
317 e += len;
318 sip_content = sip_content->sip_content_next;
320 p[msg->sip_msg_len] = '\0';
321 return (p);
325 * This is called just before sending the message to the transport. It
326 * creates the sip_msg_buf from the SIP headers.
329 sip_adjust_msgbuf(_sip_msg_t *msg)
331 _sip_header_t *header;
332 int ret;
333 #ifdef _DEBUG
334 int tlen = 0;
335 int clen = 0;
336 #endif
338 if (msg == NULL)
339 return (EINVAL);
341 (void) pthread_mutex_lock(&msg->sip_msg_mutex);
342 if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
344 * We could just be forwarding the message we
345 * received.
347 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
348 return (0);
352 * We are sending a new message or a message that we received
353 * but have modified it. We keep the old
354 * msgbuf till the message is freed as some
355 * headers still point to it.
358 assert(msg->sip_msg_old_buf == NULL);
359 msg->sip_msg_old_buf = msg->sip_msg_buf;
361 * We add the content-length header here, if it has not
362 * already been added.
364 header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
365 if (header != NULL) {
367 * Mark the previous header as deleted.
369 header->sip_header_state = SIP_HEADER_DELETED;
370 header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
371 header->sip_hdr_start;
373 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
374 ret = sip_add_content_length(msg, msg->sip_msg_content_len);
375 if (ret != 0) {
376 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
377 return (ret);
379 (void) pthread_mutex_lock(&msg->sip_msg_mutex);
380 msg->sip_msg_modified = B_FALSE;
382 msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
383 if (msg->sip_msg_buf == NULL) {
384 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
385 return (ret);
388 * Once the message has been sent it can not be modified
389 * any furthur as we keep a pointer to it for retransmission
391 msg->sip_msg_cannot_be_modified = B_TRUE;
393 (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
394 return (0);
398 * Copy header values into ptr
401 sip_copy_values(char *ptr, _sip_header_t *header)
403 sip_header_value_t value;
404 int tlen = 0;
405 int len = 0;
406 boolean_t first = B_TRUE;
407 char *p = ptr;
408 char *s;
409 boolean_t crlf_present = B_FALSE;
411 if (sip_parse_goto_values(header) != 0)
412 return (0);
414 len = header->sip_hdr_current - header->sip_hdr_start;
415 (void) strncpy(p, header->sip_hdr_start, len);
416 tlen += len;
417 p += len;
418 value = header->sip_hdr_parsed->value;
419 while (value != NULL) {
420 if (value->value_state != SIP_VALUE_DELETED) {
421 crlf_present = B_FALSE;
422 len = value->value_end - value->value_start;
423 if (first) {
424 (void) strncpy(p, value->value_start, len);
425 first = B_FALSE;
426 } else {
427 s = value->value_start;
428 while (*s != SIP_COMMA)
429 s--;
430 len += value->value_start - s;
431 (void) strncpy(p, s, len);
433 tlen += len;
434 p += len;
435 s = value->value_end;
436 while (s != value->value_start) {
437 if (*s == '\r' && strncmp(s, SIP_CRLF,
438 strlen(SIP_CRLF)) == 0) {
439 crlf_present = B_TRUE;
440 break;
442 s--;
444 } else {
445 if (value->next == NULL && !first && !crlf_present) {
446 s = value->value_end;
447 while (*s != '\r')
448 s--;
449 len = value->value_end - s;
450 (void) strncpy(p, s, len);
451 tlen += len;
452 p += len;
455 value = value->next;
457 return (tlen);
462 * Add content (message body) to sip_msg
465 sip_add_content(sip_msg_t sip_msg, char *content)
467 size_t len;
468 sip_content_t **loc;
469 sip_content_t *msg_content;
470 _sip_msg_t *_sip_msg;
472 if (sip_msg == NULL || content == NULL || strlen(content) == 0)
473 return (EINVAL);
474 len = strlen(content);
475 _sip_msg = (_sip_msg_t *)sip_msg;
476 (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
478 if (_sip_msg->sip_msg_cannot_be_modified) {
479 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
480 return (ENOTSUP);
483 msg_content = calloc(1, sizeof (sip_content_t));
484 if (msg_content == NULL) {
485 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
486 return (ENOMEM);
488 msg_content->sip_content_start = malloc(strlen(content) + 1);
489 if (msg_content->sip_content_start == NULL) {
490 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
491 free(msg_content);
492 return (ENOMEM);
494 (void) strncpy(msg_content->sip_content_start, content,
495 strlen(content));
496 msg_content->sip_content_start[strlen(content)] = '\0';
497 msg_content->sip_content_current = msg_content->sip_content_start;
498 msg_content->sip_content_end = msg_content->sip_content_start +
499 strlen(msg_content->sip_content_start);
500 msg_content->sip_content_allocated = B_TRUE;
502 loc = &_sip_msg->sip_msg_content;
503 while (*loc != NULL)
504 loc = &((*loc)->sip_content_next);
505 *loc = msg_content;
507 _sip_msg->sip_msg_content_len += len;
508 _sip_msg->sip_msg_len += len;
509 if (_sip_msg->sip_msg_buf != NULL)
510 _sip_msg->sip_msg_modified = B_TRUE;
511 (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
512 return (0);
516 * Free the message content
518 void
519 sip_free_content(_sip_msg_t *sip_msg)
521 sip_content_t *content;
523 if (sip_msg == NULL)
524 return;
525 content = sip_msg->sip_msg_content;
526 while (content != NULL) {
527 sip_content_t *content_tmp;
529 content_tmp = content;
530 content = content->sip_content_next;
531 if (content_tmp->sip_content_allocated)
532 free(content_tmp->sip_content_start);
533 free(content_tmp);
535 sip_msg->sip_msg_content = NULL;
540 * Add a response line to sip_response
543 sip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
545 _sip_header_t *new_header;
546 int header_size;
547 _sip_msg_t *_sip_response;
548 int ret;
550 if (sip_response == NULL || response < 0 || response_code == NULL)
551 return (EINVAL);
552 _sip_response = (_sip_msg_t *)sip_response;
553 (void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
554 if (_sip_response->sip_msg_cannot_be_modified) {
555 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
556 return (ENOTSUP);
558 header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN +
559 SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
560 strlen(SIP_CRLF);
562 new_header = sip_new_header(header_size);
563 if (new_header == NULL) {
564 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
565 return (ENOMEM);
567 new_header->sip_hdr_sipmsg = _sip_response;
569 (void) snprintf(new_header->sip_hdr_start, header_size + 1,
570 SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
572 new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
573 _sip_response->sip_msg_start_line = new_header;
574 _sip_response->sip_msg_len += header_size;
575 ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
576 &_sip_response->sip_msg_req_res);
577 if (_sip_response->sip_msg_buf != NULL)
578 _sip_response->sip_msg_modified = B_TRUE;
579 (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
580 return (ret);
584 * create a response based on the sip_request.
585 * Copies Call-ID, CSeq, From, To and Via headers from the request.
587 sip_msg_t
588 sip_create_response(sip_msg_t sip_request, int response, char *response_code,
589 char *totag, char *mycontact)
591 _sip_msg_t *new_msg;
592 _sip_msg_t *_sip_request;
593 boolean_t ttag_present;
595 if (sip_request == NULL || response_code == NULL)
596 return (NULL);
598 ttag_present = sip_get_to_tag(sip_request, NULL) != NULL;
600 new_msg = (_sip_msg_t *)sip_new_msg();
601 if (new_msg == NULL)
602 return (NULL);
603 _sip_request = (_sip_msg_t *)sip_request;
605 (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
608 * Add response line.
610 if (sip_add_response_line(new_msg, response, response_code) != 0)
611 goto error;
614 * Copy Via headers
616 if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
617 goto error;
620 * Copy From header.
622 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
623 NULL, B_FALSE)) {
624 goto error;
627 * Copy To header. If To tag is present, copy it, if not then
628 * add one if the repsonse is not provisional.
630 if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
631 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
632 NULL, B_FALSE)) {
633 goto error;
635 } else {
636 char *xtra_param;
637 boolean_t tag_alloc = B_FALSE;
638 int taglen;
640 if (totag == NULL) {
641 totag = sip_guid();
642 if (totag == NULL)
643 goto error;
644 tag_alloc = B_TRUE;
646 taglen = strlen(SIP_TAG) + strlen(totag) + 1;
647 xtra_param = (char *)malloc(taglen);
648 if (xtra_param == NULL) {
649 if (tag_alloc)
650 free(totag);
651 goto error;
653 (void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
654 if (tag_alloc)
655 free(totag);
656 if (_sip_find_and_copy_header(_sip_request, new_msg,
657 SIP_TO, xtra_param, B_FALSE)) {
658 free(xtra_param);
659 goto error;
661 free(xtra_param);
665 * Copy Call-ID header.
667 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
668 B_FALSE)) {
669 goto error;
672 * Copy CSEQ header
674 if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
675 B_FALSE)) {
676 goto error;
679 * Copy RECORD-ROUTE header, if present.
681 if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
682 NULL) {
683 if (_sip_find_and_copy_all_header(_sip_request, new_msg,
684 SIP_RECORD_ROUTE) != 0) {
685 goto error;
688 if (mycontact != NULL) {
689 if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE,
690 NULL) != 0) {
691 goto error;
694 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
695 return ((sip_msg_t)new_msg);
696 error:
697 sip_free_msg((sip_msg_t)new_msg);
698 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
699 return (NULL);
703 * NON OK ACK : MUST contain values for the Call-ID, From, and Request-URI
704 * that are equal to the values of those header fields in the orig request
705 * passed to the transport. The To header field in the ACK MUST equal the To
706 * header field in the response being acknowledged. The ACK MUST contain the
707 * top Via header field of the original request. The CSeq header field in
708 * the ACK MUST contain the same value for the sequence number as was
709 * present in the original request, but the method parameter MUST be equal
710 * to "ACK".
713 sip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
715 int seqno;
716 char *uri;
717 _sip_msg_t *_request;
718 _sip_msg_t *_response;
719 _sip_msg_t *_ack_msg;
720 int ret;
722 if (request == NULL || response == NULL || ack_msg == NULL ||
723 request == ack_msg) {
724 return (EINVAL);
726 _request = (_sip_msg_t *)request;
727 _response = (_sip_msg_t *)response;
728 _ack_msg = (_sip_msg_t *)ack_msg;
730 (void) pthread_mutex_lock(&_request->sip_msg_mutex);
731 if (_request->sip_msg_req_res == NULL) {
732 if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
733 &_request->sip_msg_req_res)) != 0) {
734 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
735 return (ret);
738 if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
739 sip_str_ptr == NULL) {
740 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
741 return (EINVAL);
743 uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
744 sip_request_uri.sip_str_len + 1);
745 if (uri == NULL) {
746 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
747 return (EINVAL);
749 (void) strncpy(uri,
750 _request->sip_msg_req_res->U.sip_request.sip_request_uri.
751 sip_str_ptr, _request->sip_msg_req_res->U.sip_request.
752 sip_request_uri.sip_str_len);
753 uri[_request->sip_msg_req_res->U.sip_request.
754 sip_request_uri.sip_str_len] = '\0';
755 if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
756 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
757 return (ret);
759 free(uri);
760 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
761 NULL, B_TRUE)) != 0) {
762 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
763 return (ret);
765 (void) _sip_find_and_copy_header(_request, _ack_msg,
766 SIP_MAX_FORWARDS, NULL, B_TRUE);
768 (void) pthread_mutex_lock(&_response->sip_msg_mutex);
769 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
770 NULL, B_TRUE)) != 0) {
771 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
772 return (ret);
774 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
775 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
776 NULL, B_TRUE)) != 0) {
777 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
778 return (ret);
780 if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
781 NULL, B_TRUE)) != 0) {
782 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
783 return (ret);
785 (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
786 seqno = sip_get_callseq_num(_request, &ret);
787 if (ret != 0)
788 return (ret);
789 if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
790 return (ret);
791 if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0)
792 return (ret);
793 return (0);
797 * This is a 2XX ACK, for others ACK is constructed differently,
798 * esp. the branch id is retained.
801 sip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
802 char *sent_by, int sent_by_port, char *via_params)
804 int seqno;
805 char *uri;
806 sip_parsed_header_t *parsed_header;
807 sip_hdr_value_t *contact_value;
808 _sip_header_t *header;
809 _sip_msg_t *_response;
810 _sip_msg_t *_ack_msg;
811 int ret;
813 if (response == NULL || response == NULL || transport == NULL)
814 return (EINVAL);
815 _response = (_sip_msg_t *)response;
816 _ack_msg = (_sip_msg_t *)ack_msg;
819 * Get URI from the response, Contact field
821 (void) pthread_mutex_lock(&_response->sip_msg_mutex);
822 if ((header = sip_search_for_header(_response, SIP_CONTACT,
823 NULL)) == NULL) {
824 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
825 return (EINVAL);
827 if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
828 0) {
829 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
830 return (ret);
832 contact_value = (sip_hdr_value_t *)parsed_header->value;
833 if (contact_value->cftr_uri.sip_str_ptr == NULL) {
834 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
835 return (EINVAL);
837 uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
838 if (uri == NULL) {
839 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
840 return (ENOMEM);
842 (void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr,
843 contact_value->cftr_uri.sip_str_len);
844 uri[contact_value->cftr_uri.sip_str_len] = '\0';
845 if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
846 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
847 return (ret);
849 free(uri);
850 if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
851 via_params)) != 0) {
852 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
853 return (ret);
856 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
857 NULL, B_TRUE)) != 0) {
858 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
859 return (ret);
861 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
862 NULL, B_TRUE)) != 0) {
863 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
864 return (ret);
866 if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
867 NULL, B_TRUE)) != 0) {
868 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
869 return (ret);
872 * Copy Max-Forward if present
874 if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
875 if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
876 SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) {
877 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
878 return (ret);
881 (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
882 seqno = sip_get_callseq_num(_response, &ret);
883 if (ret != 0)
884 return (ret);
885 if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
886 return (ret);
888 return (0);
892 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
895 sip_add_request_line(sip_msg_t sip_request, sip_method_t method,
896 char *request_uri)
898 _sip_header_t *new_header;
899 int header_size;
900 _sip_msg_t *_sip_request;
902 if (method < INVITE || method >= MAX_SIP_METHODS ||
903 request_uri == NULL || sip_request == NULL) {
904 return (EINVAL);
907 _sip_request = (_sip_msg_t *)sip_request;
908 (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
909 if (_sip_request->sip_msg_cannot_be_modified) {
910 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
911 return (ENOTSUP);
914 header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
915 strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
916 strlen(SIP_CRLF);
918 new_header = sip_new_header(header_size);
919 if (new_header == NULL) {
920 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
921 return (ENOMEM);
923 new_header->sip_hdr_sipmsg = _sip_request;
925 (void) snprintf(new_header->sip_hdr_start, header_size + 1,
926 "%s %s %s%s", sip_methods[method].name, request_uri,
927 SIP_VERSION, SIP_CRLF);
929 new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
930 _sip_request->sip_msg_start_line = new_header;
931 _sip_request->sip_msg_len += header_size;
932 (void) sip_parse_first_line(_sip_request->sip_msg_start_line,
933 &_sip_request->sip_msg_req_res);
934 if (_sip_request->sip_msg_buf != NULL)
935 _sip_request->sip_msg_modified = B_TRUE;
936 (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
937 return (0);