40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
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 *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * or http://www.opensolaris.org/os/licensing.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
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 *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
2c2c41837e330b002c4220a39638150db504fe0evi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
2c2c41837e330b002c4220a39638150db504fe0evi#include <stdio.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <assert.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <errno.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <pthread.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <stdlib.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <string.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <sip.h>
2c2c41837e330b002c4220a39638150db504fe0evi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_msg.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_miscdefs.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_parse_generic.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Response consists of SIP version, response code, response phrase and CRLF.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#define SIP_RESPONSE "%s %d %s%s"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid sip_free_content(_sip_msg_t *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Allocate a new sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_msg_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_new_msg()
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg = calloc(1, sizeof (_sip_msg_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg->sip_msg_ref_cnt = 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_msg_t)sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
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 */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_destroy_msg(_sip_msg_t *_sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef __solaris__
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(mutex_held(&_sip_msg->sip_msg_mutex));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) sip_delete_start_line_locked(_sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(_sip_msg->sip_msg_ref_cnt == 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_delete_all_headers((sip_msg_t)_sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_content(_sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_msg->sip_msg_buf != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(_sip_msg->sip_msg_buf);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_msg->sip_msg_old_buf != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(_sip_msg->sip_msg_old_buf);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (_sip_msg->sip_msg_req_res != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_message_type_t *sip_msg_type_ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_msg->sip_msg_req_res->is_request) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_request_t *reqline;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (reqline->sip_parse_uri != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_parsed_uri(reqline->sip_parse_uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi reqline->sip_parse_uri = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(_sip_msg->sip_msg_req_res);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg->sip_msg_req_res = sip_msg_type_ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(_sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free a sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_free_msg(sip_msg_t sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Hold a sip msg struct.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_hold_msg(sip_msg_t sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Clone a message
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_msg_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_clone_msg(sip_msg_t sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *new_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *sip_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *new_content = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg = (_sip_msg_t *)sip_new_msg();
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg = (_sip_msg_t *)sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get start line
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_copy_start_line(_sip_msg, new_msg) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_copy_all_headers(_sip_msg, new_msg) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content = _sip_msg->sip_msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_content != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content = calloc(1, sizeof (sip_content_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg_content == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = sip_content->sip_content_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content->sip_content_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start = malloc(len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg_content->sip_content_start == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(msg_content->sip_content_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content->sip_content_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start[len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_current =
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_end = msg_content->sip_content_start +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_allocated = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_content_len += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_len += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_msg->sip_msg_content == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_content = msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi else
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_content->sip_content_next = msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_content = msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content = sip_content->sip_content_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
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 */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&new_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_msg->sip_msg_buf == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg->sip_msg_cannot_be_modified = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Return the SIP message as a string. Caller frees the string
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vichar *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_msg_to_str(sip_msg_t sip_msg, int *error)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *msgstr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = EINVAL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg = (_sip_msg_t *)sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msgstr = sip_msg_to_msgbuf(msg, error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (msgstr);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Given a message generate a string that includes all the headers and the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * content.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vichar *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_msg_to_msgbuf(_sip_msg_t *msg, int *error)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *p;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *e;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *sip_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef _DEBUG
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int tlen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int clen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = EINVAL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef __solaris__
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(mutex_held(&msg->sip_msg_mutex));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi p = (char *)malloc(msg->sip_msg_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (p == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ENOMEM;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi e = p;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the start line
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg->sip_msg_start_line != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = msg->sip_msg_start_line->sip_hdr_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_start_line->sip_hdr_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi e += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef _DEBUG
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header = sip_search_for_header(msg, NULL, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (header != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (header->sip_header_state != SIP_HEADER_DELETED) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (header->sip_header_state ==
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_HEADER_DELETED_VAL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = sip_copy_values(e, header);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = header->sip_hdr_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header->sip_hdr_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(e, header->sip_hdr_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef _DEBUG
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(tlen <= msg->sip_msg_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header = sip_search_for_header(msg, NULL, header);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi e += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content = msg->sip_msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (sip_content != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = sip_content->sip_content_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content->sip_content_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef _DEBUG
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi clen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(clen <= msg->sip_msg_content_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(tlen <= msg->sip_msg_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(e, sip_content->sip_content_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi e += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content = sip_content->sip_content_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi p[msg->sip_msg_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (p);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is called just before sending the message to the transport. It
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * creates the sip_msg_buf from the SIP headers.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_adjust_msgbuf(_sip_msg_t *msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#ifdef _DEBUG
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int tlen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int clen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#endif
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We could just be forwarding the message we
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * received.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
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 */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(msg->sip_msg_old_buf == NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_old_buf = msg->sip_msg_buf;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * We add the content-length header here, if it has not
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * already been added.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (header != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Mark the previous header as deleted.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header->sip_header_state = SIP_HEADER_DELETED;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header->sip_hdr_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ret = sip_add_content_length(msg, msg->sip_msg_content_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_modified = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg->sip_msg_buf == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
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 */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg->sip_msg_cannot_be_modified = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy header values into ptr
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_copy_values(char *ptr, _sip_header_t *header)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_header_value_t value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int tlen = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int len = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t first = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *p = ptr;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *s;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t crlf_present = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_parse_goto_values(header) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = header->sip_hdr_current - header->sip_hdr_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(p, header->sip_hdr_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi p += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value = header->sip_hdr_parsed->value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (value != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (value->value_state != SIP_VALUE_DELETED) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf_present = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = value->value_end - value->value_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (first) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(p, value->value_start, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi first = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s = value->value_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (*s != SIP_COMMA)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s--;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len += value->value_start - s;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(p, s, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi p += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s = value->value_end;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (s != value->value_start) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (*s == '\r' && strncmp(s, SIP_CRLF,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(SIP_CRLF)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi crlf_present = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi break;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s--;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (value->next == NULL && !first && !crlf_present) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s = value->value_end;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (*s != '\r')
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi s--;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = value->value_end - s;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(p, s, len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tlen += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi p += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi value = value->next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (tlen);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add content (message body) to sip_msg
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_content(sip_msg_t sip_msg, char *content)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi size_t len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t **loc;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL || content == NULL || strlen(content) == 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi len = strlen(content);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg = (_sip_msg_t *)sip_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_msg->sip_msg_cannot_be_modified) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOTSUP);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content = calloc(1, sizeof (sip_content_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg_content == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start = malloc(strlen(content) + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (msg_content->sip_content_start == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(msg_content);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(msg_content->sip_content_start, content,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(content));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_start[strlen(content)] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_current = msg_content->sip_content_start;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_end = msg_content->sip_content_start +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(msg_content->sip_content_start);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi msg_content->sip_content_allocated = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi loc = &_sip_msg->sip_msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (*loc != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi loc = &((*loc)->sip_content_next);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *loc = msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg->sip_msg_content_len += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg->sip_msg_len += len;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_msg->sip_msg_buf != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg->sip_msg_modified = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Free the message content
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_free_content(_sip_msg_t *sip_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi content = sip_msg->sip_msg_content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (content != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_content_t *content_tmp;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi content_tmp = content;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi content = content->sip_content_next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (content_tmp->sip_content_allocated)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(content_tmp->sip_content_start);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(content_tmp);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg->sip_msg_content = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add a response line to sip_response
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *new_header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int header_size;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_sip_response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_response == NULL || response < 0 || response_code == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_response = (_sip_msg_t *)sip_response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_response->sip_msg_cannot_be_modified) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOTSUP);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header = sip_new_header(header_size);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_header == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_sipmsg = _sip_response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(new_header->sip_hdr_start, header_size + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_response->sip_msg_start_line = new_header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_response->sip_msg_len += header_size;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_sip_response->sip_msg_req_res);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_response->sip_msg_buf != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_response->sip_msg_modified = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * create a response based on the sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copies Call-ID, CSeq, From, To and Via headers from the request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_msg_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_response(sip_msg_t sip_request, int response, char *response_code,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *totag, char *mycontact)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *new_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t ttag_present;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_request == NULL || response_code == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ttag_present = sip_get_to_tag(sip_request, NULL) != NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_msg = (_sip_msg_t *)sip_new_msg();
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_request = (_sip_msg_t *)sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add response line.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_add_response_line(new_msg, response, response_code) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Via headers
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy From header.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_FALSE)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy To header. If To tag is present, copy it, if not then
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * add one if the repsonse is not provisional.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_FALSE)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *xtra_param;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t tag_alloc = B_FALSE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int taglen;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (totag == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi totag = sip_guid();
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (totag == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tag_alloc = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi taglen = strlen(SIP_TAG) + strlen(totag) + 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xtra_param = (char *)malloc(taglen);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (xtra_param == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tag_alloc)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(totag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tag_alloc)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(totag);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_TO, xtra_param, B_FALSE)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(xtra_param);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(xtra_param);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Call-ID header.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi B_FALSE)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy CSEQ header
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi B_FALSE)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy RECORD-ROUTE header, if present.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_find_and_copy_all_header(_sip_request, new_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_RECORD_ROUTE) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (mycontact != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi goto error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vierror:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_free_msg((sip_msg_t)new_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
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".
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int seqno;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_ack_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (request == NULL || response == NULL || ack_msg == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi request == ack_msg) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _request = (_sip_msg_t *)request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _response = (_sip_msg_t *)response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _ack_msg = (_sip_msg_t *)ack_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_request->sip_msg_req_res == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_request->sip_msg_req_res)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_request_uri.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(uri,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _request->sip_msg_req_res->U.sip_request.sip_request_uri.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_str_ptr, _request->sip_msg_req_res->U.sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_request_uri.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri[_request->sip_msg_req_res->U.sip_request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_request_uri.sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) _sip_find_and_copy_header(_request, _ack_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MAX_FORWARDS, NULL, B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi seqno = sip_get_callseq_num(_request, &ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This is a 2XX ACK, for others ACK is constructed differently,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * esp. the branch id is retained.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *sent_by, int sent_by_port, char *via_params)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int seqno;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *uri;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_parsed_header_t *parsed_header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hdr_value_t *contact_value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_ack_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (response == NULL || response == NULL || transport == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _response = (_sip_msg_t *)response;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _ack_msg = (_sip_msg_t *)ack_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get URI from the response, Contact field
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((header = sip_search_for_header(_response, SIP_CONTACT,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL)) == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi contact_value = (sip_hdr_value_t *)parsed_header->value;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (contact_value->cftr_uri.sip_str_ptr == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (uri == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi contact_value->cftr_uri.sip_str_len);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uri[contact_value->cftr_uri.sip_str_len] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(uri);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi via_params)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copy Max-Forward if present
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_response->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi seqno = sip_get_callseq_num(_response, &ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Request-Line = Method SP Request-URI SP SIP-Version CRLF
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_request_line(sip_msg_t sip_request, sip_method_t method,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *request_uri)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *new_header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int header_size;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method < INVITE || method >= MAX_SIP_METHODS ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi request_uri == NULL || sip_request == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_request = (_sip_msg_t *)sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_request->sip_msg_cannot_be_modified) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOTSUP);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header = sip_new_header(header_size);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (new_header == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_sipmsg = _sip_request;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) snprintf(new_header->sip_hdr_start, header_size + 1,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi "%s %s %s%s", sip_methods[method].name, request_uri,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_VERSION, SIP_CRLF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_request->sip_msg_start_line = new_header;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_request->sip_msg_len += header_size;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) sip_parse_first_line(_sip_request->sip_msg_start_line,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &_sip_request->sip_msg_req_res);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (_sip_request->sip_msg_buf != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_request->sip_msg_modified = B_TRUE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}