⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_msg.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_msg.c	1.58	06/08/16 SMI"#include"sip_msg.h"#include "sip_miscdefs.h"#include "sip_parse_generic.h"#define	SIP_RESPONSE	"%s %d %s%s"#define	SIP_REQUEST	"%s %s%s"/* list of sent-by values registered by the UA */sent_by_list_t	*sip_sent_by = NULL;int		sip_sent_by_count = 0;static int sip_add_name_aspec(_sip_msg_t *, char *, char *, char *, boolean_t,    char *, char *);/* Allocate a new sip msg struct. */sip_msg_tsip_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);}/* Copy header values into ptr */intsip_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			*e;	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) {			len = value->value_end - value->value_start;			if (first) {				(void) strncpy(p, value->value_start, len);				first = B_FALSE;			} else {				e = value->value_start;				while (*e != SIP_COMMA)					e--;				len += value->value_start - e;				(void) strncpy(p, e, len);			}			tlen += len;			p += len;		}		value = value->next;	}	return (tlen);}/* Returns number of bytes in the given int */static intsip_num_of_bytes(int num){	int	num_of_bytes = 0;	do {		num_of_bytes += 1;		num = num / 10;	} while (num > 0);	return (num_of_bytes);}/* * This is called just before sending the message to the transport. It * creates the sip_msg_buf from the SIP headers. */intsip_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)) {		/*		 * We could just be forwarding the message we		 * received.		 */		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);		return (0);	}	/*	 * We are sending a new message or a message that we received	 * but have modified it. We keep the old	 * msgbuf till the message is freed as some	 * headers still point to it.	 */	assert(msg->sip_msg_old_buf == NULL);	msg->sip_msg_old_buf = msg->sip_msg_buf;	/*	 * We add the content-length header here, if it has not	 * already been added.	 */	header = sip_search_for_header(msg, SIP_CONTENT_LENGTH, NULL);	if (header != NULL) {		/*		 * Mark the previous header as deleted.		 */		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_lock(&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);	}	/*	 * Once the message has been sent it can not be modified	 * any furthur as we keep a pointer to it for retransmission	 */	msg->sip_msg_cannot_be_modified = B_TRUE;	(void) pthread_mutex_unlock(&msg->sip_msg_mutex);	return (0);}/* Free the message content */voidsip_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;}/* Free all resources */voidsip_destroy_msg(_sip_msg_t *_sip_msg){	(void) sip_delete_start_line(_sip_msg);	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);	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_type_ptr->is_request) {			sip_request_t	*reqline;			reqline = &sip_msg_type_ptr->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_unlock(&_sip_msg->sip_msg_mutex);	free(_sip_msg);}/* Free a sip msg struct. */voidsip_free_msg(sip_msg_t sip_msg){	_sip_msg_t	*msg;	if (sip_msg == NULL)		return;	msg = (_sip_msg_t *)sip_msg;	SIP_MSG_REFCNT_DECR(msg);}/* Hold a sip msg struct. */voidsip_hold_msg(sip_msg_t sip_msg){	_sip_msg_t	*msg;	if (sip_msg == NULL)		return;	msg = (_sip_msg_t *)sip_msg;	SIP_MSG_REFCNT_INCR(msg);}/* Check if the message can be modified. */boolean_tsip_ok_to_modify_message(_sip_msg_t *_sip_msg){	if (_sip_msg == NULL)		return (B_FALSE);#ifdef	__solaris__	assert(mutex_held(&_sip_msg->sip_msg_mutex));#endif	if (_sip_msg->sip_msg_cannot_be_modified)		return (B_FALSE);	if (_sip_msg->sip_msg_buf != NULL)		_sip_msg->sip_msg_modified = B_TRUE;	return (B_TRUE);}/* Add a response line to sip_response */intsip_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_ok_to_modify_message(_sip_response)) {		(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);		return (ENOTSUP);	}	header_size = strlen(SIP_VERSION) + SIP_SPACE +	    SIP_SIZE_OF_STATUS_CODE + SIP_SPACE + 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);	(void) pthread_mutex_unlock(&_sip_response->sip_msg_mutex);	return (ret);}/* * create a response based on the sip_request. * Copies Call-ID, CSeq, From, To and Via headers from the request. */sip_msg_tsip_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);	/*	 * Add response line.	 */	if (sip_add_response_line(new_msg, response, response_code) != 0)		goto error;	/*	 * Copy Via headers	 */	if (_sip_find_and_copy_all_header(_sip_request, new_msg, SIP_VIA) != 0)		goto error;	/*	 * Copy From header.	 */	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_FROM,	    NULL)) {		goto error;	}	/*	 * Copy To header. If To tag is present, copy it, if not then	 * add one if the repsonse is not provisional.	 */	if (ttag_present || (totag == NULL && response == SIP_TRYING)) {		if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_TO,		    NULL)) {			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)) {			free(xtra_param);			goto error;		}		free(xtra_param);	}	/*	 * Copy Call-ID header.	 */	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CALL_ID, NULL))		goto error;	/*	 * Copy CSEQ header	 */	if (_sip_find_and_copy_header(_sip_request, new_msg, SIP_CSEQ, NULL))		goto error;	/*	 * Copy RECORD-ROUTE header, if present.	 */	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);}/* Add quotes to the give str and return the quoted string */static char *sip_add_aquot_to_str(char *str, boolean_t *alloc){	char 		*new_str;	char 		*tmp = str;	int		size;	while (isspace(*tmp))		tmp++;	*alloc = B_FALSE;	if (*tmp != SIP_LAQUOT) {		size = strlen(str) + 2 * sizeof (char);		new_str = calloc(1, size + 1);		if (new_str == NULL)			return (NULL);		new_str[0] = SIP_LAQUOT;		new_str[1] = '\0';		(void) strncat(new_str, str, strlen(str));		(void) strncat(new_str, ">", 1);		new_str[size] = '\0';		*alloc = B_TRUE;		return (new_str);	}	return (str);}/* Add an empty header */static intsip_add_empty_hdr(sip_msg_t sip_msg, char *hdr_name){	_sip_header_t	*new_header;	int 		header_size;	_sip_msg_t 	*_sip_msg;	int		csize = sizeof (char);	if (sip_msg == NULL || hdr_name == NULL)		return (EINVAL);	_sip_msg = (_sip_msg_t *)sip_msg;	(void) pthread_mutex_lock(&_sip_msg->sip_msg_mutex);	if (!sip_ok_to_modify_message(_sip_msg)) {		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);		return (ENOTSUP);	}	header_size = strlen(hdr_name) + SIP_SPACE + csize;	new_header = sip_new_header(header_size);	if (new_header == NULL) {		(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);		return (ENOMEM);	}	(void) snprintf(new_header->sip_hdr_start, header_size + 1,	    "%s %c",  hdr_name, SIP_HCOLON);	_sip_add_header(_sip_msg, new_header, B_TRUE, B_FALSE, hdr_name);	(void) pthread_mutex_unlock(&_sip_msg->sip_msg_mutex);	return (0);}/* Generic function to add a header with two strings to message */static intsip_add_2strs_to_msg(sip_msg_t sip_msg, char *hdr_name, char *str1,    boolean_t qstr1, char *str2, char *plist, char sep)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -