/*
 * OpenMRCP - Open Source Media Resource Control Protocol Stack
 * Copyright (C) 2007, Cepstral LLC
 *
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Author(s):
 * Arsen Chaloyan <achaloyan@yahoo.com>
 *
 * Contributor(s):
 *
 */

#include "mrcp_message.h"
#include "mrcp_generic_header.h"
#include "apt_string_table.h"

/* protocol name used in version string */
#define MRCP_NAME               "MRCP"

#define MRCP_CHANNEL_IDENTIFIER "Channel-Identifier"

/* separators used in mrcp version string parse/generate */
#define MRCP_NAME_VERSION_SEPARATOR        '/'
#define MRCP_VERSION_MAJOR_MINOR_SEPARATOR '.'

#define MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT 4


/* string table of mrcp request-states (mrcp_request_state_t) */
static const apt_string_table_item_t mrcp_request_state_string_table[] = {
	{"COMPLETE",    8,0},
	{"IN-PROGRESS",11,0},
	{"PENDING",     7,0}
};


/* parses mrcp version */
static mrcp_version_t mrcp_version_parse(char *field)
{
	mrcp_version_t version = MRCP_VERSION_UNKNOWN;
	char *name = apt_read_field(&field,MRCP_NAME_VERSION_SEPARATOR,1);
	if(name && apt_str_compare(name,MRCP_NAME) == TRUE) {
		name = apt_read_field(&field,MRCP_VERSION_MAJOR_MINOR_SEPARATOR,1);
		if(name) {
			switch(*name)
			{
				case '1': version = MRCP_VERSION_1; break;
				case '2': version = MRCP_VERSION_2; break;
				default: ;
			}
		}
	}
	return version;
}

/* generates mrcp version */
static size_t mrcp_version_generate(mrcp_version_t version, char *field)
{
	int ret = sprintf(field,"%s%c%d%c0",MRCP_NAME,MRCP_NAME_VERSION_SEPARATOR,version,MRCP_VERSION_MAJOR_MINOR_SEPARATOR);
	if(ret < 0) {
		ret = 0;
	}
	return ret;
}

/* parses mrcp request-state used in mrcp response and event */
static APR_INLINE mrcp_request_state_t mrcp_request_state_parse(const char* str_request_state)
{
	return apt_string_table_find(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,str_request_state);
}

/* generates mrcp request-state used in mrcp response and event */
static size_t mrcp_request_state_generate(mrcp_request_state_t request_state, char* str_request_state)
{
	size_t length = 0;
	const char *name;
	name = apt_string_table_get(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,request_state);
	if(request_state < MRCP_REQUEST_STATE_COUNT) {
		length = strlen(name);
		memcpy(str_request_state,name,length);
	}
	return length;
}

/* parses mrcp request-id */
static APR_INLINE mrcp_request_id mrcp_request_id_parse(const char *field)
{
	return apt_size_value_parse(field);
}

/* generates mrcp request-id */
static APR_INLINE size_t  mrcp_request_id_generate(mrcp_request_id request_id, char *field)
{
	return apt_size_value_generate(request_id,field);
}

static APR_INLINE mrcp_status_code_t mrcp_status_code_parse(const char *field)
{
	return apt_size_value_parse(field);
}

static APR_INLINE size_t  mrcp_status_code_generate(mrcp_status_code_t status_code, char *field)
{
	return apt_size_value_generate(status_code,field);
}


/* parses mrcp request-line */
static mrcp_status_t mrcp_request_line_parse(mrcp_start_line_t *start_line, char *line)
{
	char *field;

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse request-id in request-line \n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->request_id = mrcp_request_id_parse(field);

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse mrcp-version in request-line \n");
		return MRCP_STATUS_FAILURE;
	}

	start_line->request_state = mrcp_request_state_parse(field);
	if(start_line->request_state == MRCP_REQUEST_STATE_UNKNOWN) {
		/* request-line */
		start_line->message_type = MRCP_MESSAGE_TYPE_REQUEST;
	}
	else {
		/* event line */
		start_line->message_type = MRCP_MESSAGE_TYPE_EVENT;

		field = apt_read_field(&line,APT_TOKEN_SP,1);
	}

	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse mrcp-version in request-line \n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->version = mrcp_version_parse(field);
	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp request-line */
static size_t mrcp_request_line_generate(mrcp_start_line_t *start_line, char *line)
{
	size_t offset = 0;
	size_t length = strlen(start_line->method_name);
	memcpy(line+offset,start_line->method_name,length);
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	length = mrcp_request_id_generate(start_line->request_id,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	if(start_line->message_type == MRCP_MESSAGE_TYPE_REQUEST) {
		if(start_line->status_code != MRCP_STATUS_CODE_UNKNOWN) {
			length = mrcp_status_code_generate(start_line->status_code,line+offset);
			if(length == 0) {
				return length;
			}
			offset += length;
			line[offset++] = APT_TOKEN_SP;
		}
	}
	else if(start_line->message_type == MRCP_MESSAGE_TYPE_EVENT) {
		length = mrcp_request_state_generate(start_line->request_state,line+offset);
		if(length == 0) {
			return length;
		}
		offset += length;
		line[offset++] = APT_TOKEN_SP;
	}

	length = mrcp_version_generate(start_line->version,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	return offset;
}

/* parses mrcp response-line */
static mrcp_status_t mrcp_response_line_parse(mrcp_start_line_t *start_line, char *line)
{
	char *field;

	start_line->length = 0;
	if(start_line->version == MRCP_VERSION_2) {
		field = apt_read_field(&line,APT_TOKEN_SP,1);
		if(!field) {
			apt_log(APT_PRIO_WARNING,"cannot parse message-length in response-line \n");
			return MRCP_STATUS_FAILURE;
		}
		start_line->length = apt_size_value_parse(field);
	}

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse request-id in response-line \n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->request_id = mrcp_request_id_parse(field);

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse status-code in response-line \n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->status_code = mrcp_status_code_parse(field);

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse request-state in response-line \n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->request_state = mrcp_request_state_parse(field);
	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp response-line */
static size_t mrcp_response_line_generate(mrcp_start_line_t *start_line, char *line)
{
	size_t offset = 0;
	size_t length;

	length = mrcp_version_generate(start_line->version,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	length = mrcp_request_id_generate(start_line->request_id,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	length = mrcp_status_code_generate(start_line->status_code,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	length = mrcp_request_state_generate(start_line->request_state,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	return offset;
}


/* parses mrcp v2 start-line */
static mrcp_status_t mrcp_v2_start_line_parse(mrcp_start_line_t *start_line, char *line, apr_pool_t *pool)
{
	char *field;

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse message-length in v2 start-line\n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->length = apt_size_value_parse(field);

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot parse request-id in v2 start-line\n");
		return MRCP_STATUS_FAILURE;
	}
	start_line->request_id = mrcp_request_id_parse(field);
	if(start_line->request_id == 0 && *field != '0') {
		/* parsing mrcp v2 request or event */
		start_line->message_type = MRCP_MESSAGE_TYPE_REQUEST;
		start_line->method_name = apr_pstrdup(pool,field);

		field = apt_read_field(&line,APT_TOKEN_SP,1);
		if(!field) {
			apt_log(APT_PRIO_WARNING,"cannot parse request-id in v2 start-line\n");
			return MRCP_STATUS_FAILURE;
		}
		start_line->request_id = mrcp_request_id_parse(field);

		field = apt_read_field(&line,APT_TOKEN_SP,1);
		if(!field) {
			apt_log(APT_PRIO_WARNING,"cannot parse request-state in v2 start-line\n");
			return MRCP_STATUS_FAILURE;
		}
		if(*field != '\0') {
			start_line->request_state = mrcp_request_state_parse(field);
			start_line->message_type = MRCP_MESSAGE_TYPE_EVENT;
		}
	}
	else {
		/* parsing mrcp v2 response */
		start_line->message_type = MRCP_MESSAGE_TYPE_RESPONSE;

		field = apt_read_field(&line,APT_TOKEN_SP,1);
		if(!field) {
			apt_log(APT_PRIO_WARNING,"cannot parse status-code in v2 start-line \n");
			return MRCP_STATUS_FAILURE;
		}
		start_line->status_code = mrcp_status_code_parse(field);

		field = apt_read_field(&line,APT_TOKEN_SP,1);
		if(!field) {
			apt_log(APT_PRIO_WARNING,"cannot parse request-state in v2 start-line \n");
			return MRCP_STATUS_FAILURE;
		}
		start_line->request_state = mrcp_request_state_parse(field);
	}

	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp v2 start-line */
static size_t mrcp_v2_start_line_generate(mrcp_start_line_t *start_line, char *line)
{
	size_t offset = 0;
	size_t length;

	length = mrcp_version_generate(start_line->version,line+offset);
	if(length == 0) {
		return length;
	}
	offset += length;
	line[offset++] = APT_TOKEN_SP;

	start_line->length = offset; /* length is temrorary used to store offset */
	/* reserving MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT space for start_line->length */
	memset(line+offset,APT_TOKEN_SP,MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT+1);
	offset += MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT+1;

	if(start_line->message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
		length = mrcp_request_id_generate(start_line->request_id,line+offset);
		if(length == 0) {
			return length;
		}
		offset += length;
		line[offset++] = APT_TOKEN_SP;

		length = mrcp_status_code_generate(start_line->status_code,line+offset);
		if(length == 0) {
			return length;
		}
		offset += length;
		line[offset++] = APT_TOKEN_SP;

		length = mrcp_request_state_generate(start_line->request_state,line+offset);
		if(length == 0) {
			return length;
		}
		offset += length;
	}
	else {
		length = strlen(start_line->method_name);
		memcpy(line+offset,start_line->method_name,length);
		offset += length;
		line[offset++] = APT_TOKEN_SP;

		length = mrcp_request_id_generate(start_line->request_id,line+offset);
		if(length == 0) {
			return length;
		}
		offset += length;

		if(start_line->message_type == MRCP_MESSAGE_TYPE_EVENT) {
			line[offset++] = APT_TOKEN_SP;
			length = mrcp_request_state_generate(start_line->request_state,line+offset);
			if(length == 0) {
				return length;
			}
			offset += length;
		}
	}
	return offset;
}



/* initializes mrcp start-line */
void mrcp_start_line_init(mrcp_start_line_t *start_line)
{
	start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
	start_line->version = MRCP_VERSION_UNKNOWN;
	start_line->length = 0;
	start_line->request_id = 0;
	start_line->method_name = NULL;
	start_line->status_code = MRCP_STATUS_CODE_UNKNOWN;
	start_line->request_state = MRCP_REQUEST_STATE_UNKNOWN;
}

/* parses mrcp start-line */
mrcp_status_t mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	char *line;
	char *field;
	mrcp_status_t status = MRCP_STATUS_SUCCESS;
	start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
	line = apt_read_line(text_stream);
	if(!line) {
		apt_log(APT_PRIO_WARNING,"cannot parse mrcp start-line \n");
		return MRCP_STATUS_FAILURE;
	}

	field = apt_read_field(&line,APT_TOKEN_SP,1);
	if(!field) {
		apt_log(APT_PRIO_WARNING,"cannot read the first field in start-line\n");
		return MRCP_STATUS_FAILURE;
	}

	if(field == strstr(field,MRCP_NAME)) {
		start_line->version = mrcp_version_parse(field);

		if(start_line->version == MRCP_VERSION_1) {
			/* parsing mrcp v1 response */
			start_line->message_type = MRCP_MESSAGE_TYPE_RESPONSE;
			status = mrcp_response_line_parse(start_line,line);
		}
		else if(start_line->version == MRCP_VERSION_2) {
			/* parsing mrcp v2 start-line (request/response/event) */
			status = mrcp_v2_start_line_parse(start_line,line,pool);
		}
		else {
			apt_log(APT_PRIO_WARNING,"unknown mrcp version\n");
			return MRCP_STATUS_FAILURE;
		}
	}
	else {
		/* parsing mrcp v1 request or event */
		start_line->method_name = apr_pstrdup(pool,field);
		status = mrcp_request_line_parse(start_line,line);
	}
	return status;
}

/* generates mrcp start-line */
mrcp_status_t mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream)
{
	mrcp_status_t status = MRCP_STATUS_FAILURE;
	size_t length = 0;
	if(start_line->version == MRCP_VERSION_1) {
		switch(start_line->message_type) {
			case MRCP_MESSAGE_TYPE_REQUEST:
				length = mrcp_request_line_generate(start_line,text_stream->pos);
				break;
			case MRCP_MESSAGE_TYPE_RESPONSE:
				length = mrcp_response_line_generate(start_line,text_stream->pos);
				break;
			case MRCP_MESSAGE_TYPE_EVENT:
				length = mrcp_request_line_generate(start_line,text_stream->pos);
				break;
			default:
				break;
		}
	}
	else if(start_line->version == MRCP_VERSION_2) {
		length = mrcp_v2_start_line_generate(start_line,text_stream->pos);
	}

	if(length > 0) {
		status = MRCP_STATUS_SUCCESS;
		text_stream->pos += length;
		apt_insert_end_of_line(text_stream);
	}
	
	return status;
}

/* finalizes mrcp start-line generation */
mrcp_status_t mrcp_start_line_finalize(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream)
{
	if(start_line->version == MRCP_VERSION_2) {
		/* message-length includes the number of bytes that specify the message-length in the header */
		/* too comlex to generate!!! see the discussion */
		/* http://www1.ietf.org/mail-archive/web/speechsc/current/msg01734.html */
		size_t offset;
		char *field = text_stream->buffer + start_line->length; /* length is temrorary used to store offset */
		text_stream->size -= MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT;
		offset = apt_var_length_value_generate(&text_stream->size,MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT,field);
		if(!offset) {
			return MRCP_STATUS_FAILURE;
		}
		field[offset] = APT_TOKEN_SP;
		start_line->length += offset;

		offset = MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT - offset;
		if(offset) {
			memmove(text_stream->buffer+offset,text_stream->buffer,start_line->length);
			text_stream->buffer += offset;
		}
	}

	start_line->length = text_stream->size;
	return MRCP_STATUS_SUCCESS;
}


/* initializes mrcp channel-identifier */
void mrcp_channel_id_init(mrcp_channel_id *channel_id)
{
	channel_id->session_id.hex_str = NULL;
	channel_id->session_id.length = 0;
	channel_id->resource_name = NULL;
	channel_id->resource_id = 0;
}

/* parses mrcp channel-identifier */
mrcp_status_t mrcp_channel_id_parse(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	char *line;
	char *field;

	do {
		line = apt_read_line(text_stream);
		if(!line || *line == '\0') {
			return MRCP_STATUS_FAILURE;
		}
		
		field = apt_read_field(&line,':',1);
		if(apt_str_compare(field,MRCP_CHANNEL_IDENTIFIER) == TRUE) {
			break;
		}

		/* skipping header, expected channel identifier first */
	}
	while(line);

	field = apt_read_field(&line,'@',1);
	channel_id->session_id.hex_str = apr_pstrdup(pool,field);
	channel_id->session_id.length = line - field - 1;
	channel_id->resource_name = apr_pstrdup(pool,line);
	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp channel-identifier */
mrcp_status_t mrcp_channel_id_generate(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream)
{
	int length;
	length = sprintf(text_stream->pos,"%s:%s@%s",MRCP_CHANNEL_IDENTIFIER,channel_id->session_id.hex_str,channel_id->resource_name);
	if(length < 0) {
		length = 0;
	}
	text_stream->pos += length;

	apt_insert_end_of_line(text_stream);
	return MRCP_STATUS_SUCCESS;
}



/* parses mrcp message-header */
mrcp_status_t mrcp_header_parse(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	char *line;
	apt_name_value_pair_t header_field;

	mrcp_header_base_allocate(&message_header->generic_header,pool);
	mrcp_header_base_allocate(&message_header->resource_header,pool);

	do {
		line = apt_read_line(text_stream);
		if(!line) {
			return MRCP_STATUS_FAILURE;
		}
		if(*line == '\0') {
			break;
		}
		apt_name_value_pair_parse(&header_field,line);
		if(mrcp_header_base_parse(&message_header->resource_header,&header_field,pool) != MRCP_STATUS_SUCCESS) {
			if(mrcp_header_base_parse(&message_header->generic_header,&header_field,pool) != MRCP_STATUS_SUCCESS) {
				/* unknown mrcp header */
			}
		}
	}
	while(line);

	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp message-header */
mrcp_status_t mrcp_header_generate(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream)
{
	mrcp_header_base_generate(&message_header->resource_header,text_stream);
	mrcp_header_base_generate(&message_header->generic_header,text_stream);
	apt_insert_end_of_line(text_stream);
	return MRCP_STATUS_SUCCESS;
}

/* sets mrcp message-header */
mrcp_status_t mrcp_header_set(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool)
{
	mrcp_header_base_set(&message_header->resource_header,&src->resource_header,src->resource_header.property_set,pool);
	mrcp_header_base_set(&message_header->generic_header,&src->generic_header,src->generic_header.property_set,pool);
	return MRCP_STATUS_SUCCESS;
}

/* gets mrcp message-header */
mrcp_status_t mrcp_header_get(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool)
{
	mrcp_header_base_set(&message_header->resource_header,&src->resource_header,message_header->resource_header.property_set,pool);
	mrcp_header_base_set(&message_header->generic_header,&src->generic_header,message_header->generic_header.property_set,pool);
	return MRCP_STATUS_SUCCESS;
}

/* inherits mrcp message-header */
mrcp_status_t mrcp_header_inherit(mrcp_message_header_t *message_header, const mrcp_message_header_t *parent, apr_pool_t *pool)
{
	mrcp_header_base_inherit(&message_header->resource_header,&parent->resource_header,pool);
	mrcp_header_base_inherit(&message_header->generic_header,&parent->generic_header,pool);
	return MRCP_STATUS_SUCCESS;
}


/* parses mrcp message-body */
mrcp_status_t mrcp_body_parse(mrcp_message_t *message, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == MRCP_STATUS_SUCCESS) {
		mrcp_generic_header_t *generic_header = message->header.generic_header.data;
		if(generic_header && generic_header->content_length) {
			size_t length = generic_header->content_length;
			message->body = apr_palloc(pool,length+1);
			memcpy(message->body,text_stream->pos,length);
			message->body[length] = '\0';
			text_stream->pos += length;
		}
	}
	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp message-body */
mrcp_status_t mrcp_body_generate(mrcp_message_t *message, apt_text_stream_t *text_stream)
{
	if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == MRCP_STATUS_SUCCESS) {
		size_t length;
		mrcp_generic_header_t *generic_header = message->header.generic_header.data;
		if(!generic_header || !message->body) {
			return MRCP_STATUS_FAILURE;
		}
		length = generic_header->content_length;
		memcpy(text_stream->pos,message->body,length);
		text_stream->pos += length;
	}
	return MRCP_STATUS_SUCCESS;
}


/* creates mrcp message */
mrcp_message_t* mrcp_message_create(apr_pool_t *pool)
{
	mrcp_message_t *message = apr_palloc(pool,sizeof(mrcp_message_t));
	mrcp_message_init(message,pool);
	return message;
}

/* initializes mrcp message */
void mrcp_message_init(mrcp_message_t *message, apr_pool_t *pool)
{
	mrcp_start_line_init(&message->start_line);
	mrcp_channel_id_init(&message->channel_id);
	mrcp_message_header_init(&message->header);
	message->body = NULL;

	message->pool = pool;
}

/* initializes response/event message by request message */
void mrcp_message_init_by_request(mrcp_message_t *message, const mrcp_message_t *request_message)
{
	message->channel_id = request_message->channel_id;
	message->start_line.request_id = request_message->start_line.request_id;
	message->start_line.version = request_message->start_line.version;
	message->header.generic_header.accessor = request_message->header.generic_header.accessor;
	message->header.resource_header.accessor = request_message->header.resource_header.accessor;
}

/* creates mrcp request message */
mrcp_message_t* mrcp_request_create(mrcp_method_id method_id, apr_pool_t *pool)
{
	mrcp_message_t *request_message = mrcp_message_create(pool);
	request_message->start_line.message_type = MRCP_MESSAGE_TYPE_REQUEST;
	request_message->start_line.method_id = method_id;
	return request_message;
}

/* creates mrcp response message */
mrcp_message_t* mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool)
{
	mrcp_message_t *response_message = mrcp_message_create(pool);
	if(request_message) {
		mrcp_message_init_by_request(response_message,request_message);
	}
	response_message->start_line.message_type = MRCP_MESSAGE_TYPE_RESPONSE;
	response_message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
	return response_message;
}

/* creates mrcp event message */
mrcp_message_t* mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool)
{
	mrcp_message_t *event_message = mrcp_message_create(pool);
	if(request_message) {
		mrcp_message_init_by_request(event_message,request_message);
	}
	event_message->start_line.message_type = MRCP_MESSAGE_TYPE_EVENT;
	event_message->start_line.method_id = event_id;
	return event_message;
}

/* destroys mrcp message */
void mrcp_message_destroy(mrcp_message_t *message)
{
	if(message->body) {
		message->body = NULL;
	}
	mrcp_message_header_destroy(&message->header);
}
