#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sip.h>
#include "sip_msg.h"
#include "sip_miscdefs.h"
#include "sip_parse_generic.h"
#define SIP_RESPONSE "%s %d %s%s"
void sip_free_content(_sip_msg_t *);
sip_msg_t
sip_new_msg()
{
_sip_msg_t *sip_msg;
sip_msg = calloc(1, sizeof (_sip_msg_t));
if (sip_msg != NULL) {
sip_msg->sip_msg_ref_cnt = 1;
(void) pthread_mutex_init(&sip_msg->sip_msg_mutex, NULL);
}
return ((sip_msg_t)sip_msg);
}
void
sip_destroy_msg(_sip_msg_t *_sip_msg)
{
#ifdef __solaris__
assert(mutex_held(&_sip_msg->sip_msg_mutex));
#endif
(void) sip_delete_start_line_locked(_sip_msg);
assert(_sip_msg->sip_msg_ref_cnt == 0);
sip_delete_all_headers((sip_msg_t)_sip_msg);
sip_free_content(_sip_msg);
if (_sip_msg->sip_msg_buf != NULL)
free(_sip_msg->sip_msg_buf);
if (_sip_msg->sip_msg_old_buf != NULL)
free(_sip_msg->sip_msg_old_buf);
while (_sip_msg->sip_msg_req_res != NULL) {
sip_message_type_t *sip_msg_type_ptr;
sip_msg_type_ptr = _sip_msg->sip_msg_req_res->sip_next;
if (_sip_msg->sip_msg_req_res->is_request) {
sip_request_t *reqline;
reqline = &_sip_msg->sip_msg_req_res->U.sip_request;
if (reqline->sip_parse_uri != NULL) {
sip_free_parsed_uri(reqline->sip_parse_uri);
reqline->sip_parse_uri = NULL;
}
}
free(_sip_msg->sip_msg_req_res);
_sip_msg->sip_msg_req_res = sip_msg_type_ptr;
}
(void) pthread_mutex_destroy(&_sip_msg->sip_msg_mutex);
free(_sip_msg);
}
void
sip_free_msg(sip_msg_t sip_msg)
{
if (sip_msg == NULL)
return;
SIP_MSG_REFCNT_DECR((_sip_msg_t *)sip_msg);
}
void
sip_hold_msg(sip_msg_t sip_msg)
{
if (sip_msg == NULL)
return;
SIP_MSG_REFCNT_INCR((_sip_msg_t *)sip_msg);
}
sip_msg_t
sip_clone_msg(sip_msg_t sip_msg)
{
_sip_msg_t *new_msg;
_sip_msg_t *_sip_msg;
sip_content_t *sip_content;
sip_content_t *msg_content;
sip_content_t *new_content = NULL;
int len;
if (sip_msg == NULL)
return (NULL);
new_msg = (_sip_msg_t *)sip_new_msg();
if (new_msg == NULL)
return (NULL);
_sip_msg = (_sip_msg_t *)sip_msg;
if (sip_copy_start_line(_sip_msg, new_msg) != 0) {
sip_free_msg((sip_msg_t)new_msg);
return (NULL);
}
if (sip_copy_all_headers(_sip_msg, new_msg) != 0) {
sip_free_msg((sip_msg_t)new_msg);
return (NULL);
}
(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
sip_content = _sip_msg->sip_msg_content;
while (sip_content != NULL) {
msg_content = calloc(1, sizeof (sip_content_t));
if (msg_content == NULL) {
sip_free_msg((sip_msg_t)new_msg);
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
return (NULL);
}
len = sip_content->sip_content_end -
sip_content->sip_content_start;
msg_content->sip_content_start = malloc(len + 1);
if (msg_content->sip_content_start == NULL) {
sip_free_msg((sip_msg_t)new_msg);
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
return (NULL);
}
(void) strncpy(msg_content->sip_content_start,
sip_content->sip_content_start, len);
msg_content->sip_content_start[len] = '\0';
msg_content->sip_content_current =
msg_content->sip_content_start;
msg_content->sip_content_end = msg_content->sip_content_start +
len;
msg_content->sip_content_allocated = B_TRUE;
new_msg->sip_msg_content_len += len;
new_msg->sip_msg_len += len;
if (new_msg->sip_msg_content == NULL)
new_msg->sip_msg_content = msg_content;
else
new_content->sip_content_next = msg_content;
new_content = msg_content;
sip_content = sip_content->sip_content_next;
}
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
(void) pthread_mutex_lock(&new_msg->sip_msg_mutex);
new_msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)new_msg, NULL);
if (new_msg->sip_msg_buf == NULL) {
(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
sip_free_msg((sip_msg_t)new_msg);
return (NULL);
}
new_msg->sip_msg_cannot_be_modified = B_TRUE;
(void) pthread_mutex_unlock(&new_msg->sip_msg_mutex);
return ((sip_msg_t)new_msg);
}
char *
sip_msg_to_str(sip_msg_t sip_msg, int *error)
{
_sip_msg_t *msg;
char *msgstr;
if (sip_msg == NULL) {
if (error != NULL)
*error = EINVAL;
return (NULL);
}
msg = (_sip_msg_t *)sip_msg;
(void) pthread_mutex_lock(&msg->sip_msg_mutex);
msgstr = sip_msg_to_msgbuf(msg, error);
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
return (msgstr);
}
char *
sip_msg_to_msgbuf(_sip_msg_t *msg, int *error)
{
_sip_header_t *header;
int len = 0;
char *p;
char *e;
sip_content_t *sip_content;
#ifdef _DEBUG
int tlen = 0;
int clen = 0;
#endif
if (error != NULL)
*error = 0;
if (msg == NULL) {
if (error != NULL)
*error = EINVAL;
return (NULL);
}
#ifdef __solaris__
assert(mutex_held(&msg->sip_msg_mutex));
#endif
p = (char *)malloc(msg->sip_msg_len + 1);
if (p == NULL) {
if (error != 0)
*error = ENOMEM;
return (NULL);
}
e = p;
if (msg->sip_msg_start_line != NULL) {
len = msg->sip_msg_start_line->sip_hdr_end -
msg->sip_msg_start_line->sip_hdr_start;
(void) strncpy(e, msg->sip_msg_start_line->sip_hdr_start, len);
e += len;
#ifdef _DEBUG
tlen += len;
#endif
}
header = sip_search_for_header(msg, NULL, NULL);
while (header != NULL) {
if (header->sip_header_state != SIP_HEADER_DELETED) {
if (header->sip_header_state ==
SIP_HEADER_DELETED_VAL) {
len = sip_copy_values(e, header);
} else {
len = header->sip_hdr_end -
header->sip_hdr_start;
(void) strncpy(e, header->sip_hdr_start, len);
}
#ifdef _DEBUG
tlen += len;
assert(tlen <= msg->sip_msg_len);
#endif
}
header = sip_search_for_header(msg, NULL, header);
e += len;
}
sip_content = msg->sip_msg_content;
while (sip_content != NULL) {
len = sip_content->sip_content_end -
sip_content->sip_content_start;
#ifdef _DEBUG
clen += len;
assert(clen <= msg->sip_msg_content_len);
tlen += len;
assert(tlen <= msg->sip_msg_len);
#endif
(void) strncpy(e, sip_content->sip_content_start, len);
e += len;
sip_content = sip_content->sip_content_next;
}
p[msg->sip_msg_len] = '\0';
return (p);
}
int
sip_adjust_msgbuf(_sip_msg_t *msg)
{
_sip_header_t *header;
int ret;
#ifdef _DEBUG
int tlen = 0;
int clen = 0;
#endif
if (msg == NULL)
return (EINVAL);
(void) pthread_mutex_lock(&msg->sip_msg_mutex);
if ((msg->sip_msg_buf != NULL) && (!msg->sip_msg_modified)) {
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
return (0);
}
assert(msg->sip_msg_old_buf == NULL);
msg->sip_msg_old_buf = msg->sip_msg_buf;
header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);
if (header != NULL) {
header->sip_header_state = SIP_HEADER_DELETED;
header->sip_hdr_sipmsg->sip_msg_len -= header->sip_hdr_end -
header->sip_hdr_start;
}
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
ret = sip_add_content_length(msg, msg->sip_msg_content_len);
if (ret != 0) {
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
return (ret);
}
(void) pthread_mutex_lock(&msg->sip_msg_mutex);
msg->sip_msg_modified = B_FALSE;
msg->sip_msg_buf = sip_msg_to_msgbuf((sip_msg_t)msg, &ret);
if (msg->sip_msg_buf == NULL) {
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
return (ret);
}
msg->sip_msg_cannot_be_modified = B_TRUE;
(void) pthread_mutex_unlock(&msg->sip_msg_mutex);
return (0);
}
int
sip_copy_values(char *ptr, _sip_header_t *header)
{
sip_header_value_t value;
int tlen = 0;
int len = 0;
boolean_t first = B_TRUE;
char *p = ptr;
char *s;
boolean_t crlf_present = B_FALSE;
if (sip_parse_goto_values(header) != 0)
return (0);
len = header->sip_hdr_current - header->sip_hdr_start;
(void) strncpy(p, header->sip_hdr_start, len);
tlen += len;
p += len;
value = header->sip_hdr_parsed->value;
while (value != NULL) {
if (value->value_state != SIP_VALUE_DELETED) {
crlf_present = B_FALSE;
len = value->value_end - value->value_start;
if (first) {
(void) strncpy(p, value->value_start, len);
first = B_FALSE;
} else {
s = value->value_start;
while (*s != SIP_COMMA)
s--;
len += value->value_start - s;
(void) strncpy(p, s, len);
}
tlen += len;
p += len;
s = value->value_end;
while (s != value->value_start) {
if (*s == '\r' && strncmp(s, SIP_CRLF,
strlen(SIP_CRLF)) == 0) {
crlf_present = B_TRUE;
break;
}
s--;
}
} else {
if (value->next == NULL && !first && !crlf_present) {
s = value->value_end;
while (*s != '\r')
s--;
len = value->value_end - s;
(void) strncpy(p, s, len);
tlen += len;
p += len;
}
}
value = value->next;
}
return (tlen);
}
int
sip_add_content(sip_msg_t sip_msg, char *content)
{
size_t len;
sip_content_t **loc;
sip_content_t *msg_content;
_sip_msg_t *_sip_msg;
if (sip_msg == NULL || content == NULL || strlen(content) == 0)
return (EINVAL);
len = strlen(content);
_sip_msg = (_sip_msg_t *)sip_msg;
(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);
if (_sip_msg->sip_msg_cannot_be_modified) {
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
return (ENOTSUP);
}
msg_content = calloc(1, sizeof (sip_content_t));
if (msg_content == NULL) {
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
return (ENOMEM);
}
msg_content->sip_content_start = malloc(strlen(content) + 1);
if (msg_content->sip_content_start == NULL) {
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
free(msg_content);
return (ENOMEM);
}
(void) strncpy(msg_content->sip_content_start, content,
strlen(content));
msg_content->sip_content_start[strlen(content)] = '\0';
msg_content->sip_content_current = msg_content->sip_content_start;
msg_content->sip_content_end = msg_content->sip_content_start +
strlen(msg_content->sip_content_start);
msg_content->sip_content_allocated = B_TRUE;
loc = &_sip_msg->sip_msg_content;
while (*loc != NULL)
loc = &((*loc)->sip_content_next);
*loc = msg_content;
_sip_msg->sip_msg_content_len += len;
_sip_msg->sip_msg_len += len;
if (_sip_msg->sip_msg_buf != NULL)
_sip_msg->sip_msg_modified = B_TRUE;
(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);
return (0);
}
void
sip_free_content(_sip_msg_t *sip_msg)
{
sip_content_t *content;
if (sip_msg == NULL)
return;
content = sip_msg->sip_msg_content;
while (content != NULL) {
sip_content_t *content_tmp;
content_tmp = content;
content = content->sip_content_next;
if (content_tmp->sip_content_allocated)
free(content_tmp->sip_content_start);
free(content_tmp);
}
sip_msg->sip_msg_content = NULL;
}
int
sip_add_response_line(sip_msg_t sip_response, int response, char *response_code)
{
_sip_header_t *new_header;
int header_size;
_sip_msg_t *_sip_response;
int ret;
if (sip_response == NULL || response < 0 || response_code == NULL)
return (EINVAL);
_sip_response = (_sip_msg_t *)sip_response;
(void) pthread_mutex_lock(&_sip_response->sip_msg_mutex);
if (_sip_response->sip_msg_cannot_be_modified) {
(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
return (ENOTSUP);
}
header_size = strlen(SIP_VERSION) + SIP_SPACE_LEN +
SIP_SIZE_OF_STATUS_CODE + SIP_SPACE_LEN + strlen(response_code) +
strlen(SIP_CRLF);
new_header = sip_new_header(header_size);
if (new_header == NULL) {
(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
return (ENOMEM);
}
new_header->sip_hdr_sipmsg = _sip_response;
(void) snprintf(new_header->sip_hdr_start, header_size + 1,
SIP_RESPONSE, SIP_VERSION, response, response_code, SIP_CRLF);
new_header->sip_hdr_next = _sip_response->sip_msg_start_line;
_sip_response->sip_msg_start_line = new_header;
_sip_response->sip_msg_len += header_size;
ret = sip_parse_first_line(_sip_response->sip_msg_start_line,
&_sip_response->sip_msg_req_res);
if (_sip_response->sip_msg_buf != NULL)
_sip_response->sip_msg_modified = B_TRUE;
(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);
return (ret);
}
sip_msg_t
sip_create_response(sip_msg_t sip_request, int response, char *response_code,
char *totag, char *mycontact)
{
_sip_msg_t *new_msg;
_sip_msg_t *_sip_request;
boolean_t ttag_present;
if (sip_request == NULL || response_code == NULL)
return (NULL);
ttag_present = sip_get_to_tag(sip_request, NULL) != NULL;
new_msg = (_sip_msg_t *)sip_new_msg();
if (new_msg == NULL)
return (NULL);
_sip_request = (_sip_msg_t *)sip_request;
(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
if (sip_add_response_line(new_msg, response, response_code) != 0)
goto error;
if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)
goto error;
if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,
NULL, B_FALSE)) {
goto error;
}
if (ttag_present || (totag == NULL && response == SIP_TRYING)) {
if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,
NULL, B_FALSE)) {
goto error;
}
} else {
char *xtra_param;
boolean_t tag_alloc = B_FALSE;
int taglen;
if (totag == NULL) {
totag = sip_guid();
if (totag == NULL)
goto error;
tag_alloc = B_TRUE;
}
taglen = strlen(SIP_TAG) + strlen(totag) + 1;
xtra_param = (char *)malloc(taglen);
if (xtra_param == NULL) {
if (tag_alloc)
free(totag);
goto error;
}
(void) snprintf(xtra_param, taglen, "%s%s", SIP_TAG, totag);
if (tag_alloc)
free(totag);
if (_sip_find_and_copy_header(_sip_request, new_msg,
SIP_TO, xtra_param, B_FALSE)) {
free(xtra_param);
goto error;
}
free(xtra_param);
}
if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL,
B_FALSE)) {
goto error;
}
if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL,
B_FALSE)) {
goto error;
}
if (sip_search_for_header(_sip_request, SIP_RECORD_ROUTE, NULL) !=
NULL) {
if (_sip_find_and_copy_all_header(_sip_request, new_msg,
SIP_RECORD_ROUTE) != 0) {
goto error;
}
}
if (mycontact != NULL) {
if (sip_add_contact(new_msg, NULL, mycontact, B_FALSE,
NULL) != 0) {
goto error;
}
}
(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
return ((sip_msg_t)new_msg);
error:
sip_free_msg((sip_msg_t)new_msg);
(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
return (NULL);
}
int
sip_create_nonOKack(sip_msg_t request, sip_msg_t response, sip_msg_t ack_msg)
{
int seqno;
char *uri;
_sip_msg_t *_request;
_sip_msg_t *_response;
_sip_msg_t *_ack_msg;
int ret;
if (request == NULL || response == NULL || ack_msg == NULL ||
request == ack_msg) {
return (EINVAL);
}
_request = (_sip_msg_t *)request;
_response = (_sip_msg_t *)response;
_ack_msg = (_sip_msg_t *)ack_msg;
(void) pthread_mutex_lock(&_request->sip_msg_mutex);
if (_request->sip_msg_req_res == NULL) {
if ((ret = sip_parse_first_line(_request->sip_msg_start_line,
&_request->sip_msg_req_res)) != 0) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (ret);
}
}
if (_request->sip_msg_req_res->U.sip_request.sip_request_uri.
sip_str_ptr == NULL) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (EINVAL);
}
uri = (char *)malloc(_request->sip_msg_req_res->U.sip_request.
sip_request_uri.sip_str_len + 1);
if (uri == NULL) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (EINVAL);
}
(void) strncpy(uri,
_request->sip_msg_req_res->U.sip_request.sip_request_uri.
sip_str_ptr, _request->sip_msg_req_res->U.sip_request.
sip_request_uri.sip_str_len);
uri[_request->sip_msg_req_res->U.sip_request.
sip_request_uri.sip_str_len] = '\0';
if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (ret);
}
free(uri);
if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_VIA,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (ret);
}
(void) _sip_find_and_copy_header(_request, _ack_msg,
SIP_MAX_FORWARDS, NULL, B_TRUE);
(void) pthread_mutex_lock(&_response->sip_msg_mutex);
if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_FROM,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (ret);
}
if ((ret = _sip_find_and_copy_header(_request, _ack_msg, SIP_CALL_ID,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
return (ret);
}
(void) pthread_mutex_unlock(&_request->sip_msg_mutex);
seqno = sip_get_callseq_num(_request, &ret);
if (ret != 0)
return (ret);
if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
return (ret);
if ((ret = sip_adjust_msgbuf(_ack_msg)) != 0)
return (ret);
return (0);
}
int
sip_create_OKack(sip_msg_t response, sip_msg_t ack_msg, char *transport,
char *sent_by, int sent_by_port, char *via_params)
{
int seqno;
char *uri;
sip_parsed_header_t *parsed_header;
sip_hdr_value_t *contact_value;
_sip_header_t *header;
_sip_msg_t *_response;
_sip_msg_t *_ack_msg;
int ret;
if (response == NULL || response == NULL || transport == NULL)
return (EINVAL);
_response = (_sip_msg_t *)response;
_ack_msg = (_sip_msg_t *)ack_msg;
(void) pthread_mutex_lock(&_response->sip_msg_mutex);
if ((header = sip_search_for_header(_response, SIP_CONTACT,
NULL)) == NULL) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (EINVAL);
}
if ((ret = sip_parse_cftr_header(header, (void *)&parsed_header)) !=
0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
contact_value = (sip_hdr_value_t *)parsed_header->value;
if (contact_value->cftr_uri.sip_str_ptr == NULL) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (EINVAL);
}
uri = (char *)malloc(contact_value->cftr_uri.sip_str_len + 1);
if (uri == NULL) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ENOMEM);
}
(void) strncpy(uri, contact_value->cftr_uri.sip_str_ptr,
contact_value->cftr_uri.sip_str_len);
uri[contact_value->cftr_uri.sip_str_len] = '\0';
if ((ret = sip_add_request_line(_ack_msg, ACK, uri)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
free(uri);
if ((ret = sip_add_via(_ack_msg, transport, sent_by, sent_by_port,
via_params)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_TO,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_FROM,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
if ((ret = _sip_find_and_copy_header(_response, _ack_msg, SIP_CALL_ID,
NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
if (sip_search_for_header(_response, SIP_MAX_FORWARDS, NULL) != NULL) {
if ((ret = _sip_find_and_copy_header(_response, _ack_msg,
SIP_MAX_FORWARDS, NULL, B_TRUE)) != 0) {
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
return (ret);
}
}
(void) pthread_mutex_unlock(&_response->sip_msg_mutex);
seqno = sip_get_callseq_num(_response, &ret);
if (ret != 0)
return (ret);
if ((ret = sip_add_cseq(_ack_msg, ACK, seqno)) != 0)
return (ret);
return (0);
}
int
sip_add_request_line(sip_msg_t sip_request, sip_method_t method,
char *request_uri)
{
_sip_header_t *new_header;
int header_size;
_sip_msg_t *_sip_request;
if (method < INVITE || method >= MAX_SIP_METHODS ||
request_uri == NULL || sip_request == NULL) {
return (EINVAL);
}
_sip_request = (_sip_msg_t *)sip_request;
(void) pthread_mutex_lock(&_sip_request->sip_msg_mutex);
if (_sip_request->sip_msg_cannot_be_modified) {
(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
return (ENOTSUP);
}
header_size = strlen(sip_methods[method].name) + SIP_SPACE_LEN +
strlen(request_uri) + SIP_SPACE_LEN + strlen(SIP_VERSION) +
strlen(SIP_CRLF);
new_header = sip_new_header(header_size);
if (new_header == NULL) {
(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
return (ENOMEM);
}
new_header->sip_hdr_sipmsg = _sip_request;
(void) snprintf(new_header->sip_hdr_start, header_size + 1,
"%s %s %s%s", sip_methods[method].name, request_uri,
SIP_VERSION, SIP_CRLF);
new_header->sip_hdr_next = _sip_request->sip_msg_start_line;
_sip_request->sip_msg_start_line = new_header;
_sip_request->sip_msg_len += header_size;
(void) sip_parse_first_line(_sip_request->sip_msg_start_line,
&_sip_request->sip_msg_req_res);
if (_sip_request->sip_msg_buf != NULL)
_sip_request->sip_msg_modified = B_TRUE;
(void) pthread_mutex_unlock(&_sip_request->sip_msg_mutex);
return (0);
}