40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The contents of this file are subject to the terms of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Common Development and Distribution License (the "License").
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You may not use this file except in compliance with the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When distributing Covered Code, include this CDDL HEADER in each
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If applicable, add the following below this CDDL HEADER, with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * fields enclosed by brackets "[]" replaced with your own identifying
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * information: Portions Copyright [yyyy] [name of copyright owner]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
2c2c41837e330b002c4220a39638150db504fe0evi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Response consists of SIP version, response code, response phrase and CRLF.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Allocate a new sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free all resources. The lock is taken by SIP_MSG_REFCNT_DECR. The
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * thread that decrements the last refcount should take care that
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the message is not accessible to other threads before doing so.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Else, if the message is still accessible to others, it is
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * possible that the other thread could be waiting to take the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * lock when we proceed to destroy it.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free a sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Hold a sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Clone a message
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get start line
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_end = msg_content->sip_content_start +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Since this is a new message, no threads should be referring
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * to this, so it is not necessary to take the lock, however,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * since sip_msg_to_msgbuf() expects the lock to be held, we'll
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * take it here.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Return the SIP message as a string. Caller frees the string
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Given a message generate a string that includes all the headers and the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * content.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (p == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the start line
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (p);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is called just before sending the message to the transport. It
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * creates the sip_msg_buf from the SIP headers.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We could just be forwarding the message we
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * received.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We are sending a new message or a message that we received
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * but have modified it. We keep the old
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * msgbuf till the message is freed as some
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * headers still point to it.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We add the content-length header here, if it has not
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * already been added.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Mark the previous header as deleted.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ret = sip_add_content_length(msg, msg->sip_msg_content_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Once the message has been sent it can not be modified
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * any furthur as we keep a pointer to it for retransmission
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy header values into ptr
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *p = ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (*s != SIP_COMMA)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (*s != '\r')
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add content (message body) to sip_msg
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL || content == NULL || strlen(content) == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start = malloc(strlen(content) + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_current = msg_content->sip_content_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_end = msg_content->sip_content_start +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free the message content
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add a response line to sip_response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_response == NULL || response < 0 || response_code == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(new_header->sip_hdr_start, header_size + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * create a response based on the sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copies Call-ID, CSeq, From, To and Via headers from the request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_response(sip_msg_t sip_request, int response, char *response_code,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ttag_present = sip_get_to_tag(sip_request, NULL) != NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add response line.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_add_response_line(new_msg, response, response_code) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Via headers
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy From header.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy To header. If To tag is present, copy it, if not then
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * add one if the repsonse is not provisional.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Call-ID header.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy CSEQ header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy RECORD-ROUTE header, if present.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * NON OK ACK : MUST contain values for the Call-ID, From, and Request-URI
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * that are equal to the values of those header fields in the orig request
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * passed to the transport. The To header field in the ACK MUST equal the To
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * header field in the response being acknowledged. The ACK MUST contain the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * top Via header field of the original request. The CSeq header field in
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * the ACK MUST contain the same value for the sequence number as was
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * present in the original request, but the method parameter MUST be equal
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * to "ACK".
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (request == NULL || response == NULL || ack_msg == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _request->sip_msg_req_res->U.sip_request.sip_request_uri.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is a 2XX ACK, for others ACK is constructed differently,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * esp. the branch id is retained.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (response == NULL || response == NULL || transport == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get URI from the response, Contact field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((header = sip_search_for_header(_response, SIP_CONTACT,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Max-Forward if present
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Request-Line = Method SP Request-URI SP SIP-Version CRLF
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_request_line(sip_msg_t sip_request, sip_method_t method,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(new_header->sip_hdr_start, header_size + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) sip_parse_first_line(_sip_request->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);