コード例 #1
0
/** Parse header section */
APT_DECLARE(apt_bool_t) apt_header_section_parse(apt_header_section_t *header, apt_text_stream_t *stream, apr_pool_t *pool)
{
	apt_header_field_t *header_field;
	apt_bool_t result = FALSE;

	do {
		header_field = apt_header_field_parse(stream,pool);
		if(header_field) {
			if(apt_string_is_empty(&header_field->name) == FALSE) {
				/* normal header */
				apt_header_section_field_add(header,header_field);
			}
			else {
				/* empty header => exit */
				result = TRUE;
				break;
			}
		}
		else {
			/* malformed header => skip to the next one */
		}
	}
	while(apt_text_is_eos(stream) == FALSE);

	return result;
}
コード例 #2
0
ファイル: rtsp_header.c プロジェクト: Jared-Prime/UniMRCP
/** Parse RTSP header */
RTSP_DECLARE(apt_bool_t) rtsp_header_parse(rtsp_header_t *header, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
    apt_pair_t pair;
    apt_bool_t result = FALSE;

    do {
        if(apt_text_header_read(text_stream,&pair) == TRUE) {
            if(pair.name.length) {
                /* parse header_field (name/value) */
                rtsp_header_field_id id = apt_string_table_id_find(rtsp_header_string_table,RTSP_HEADER_FIELD_COUNT,&pair.name);
                if(id < RTSP_HEADER_FIELD_COUNT) {
                    if(rtsp_header_field_parse(header,id,&pair.value,pool) == TRUE) {
                        rtsp_header_property_add(&header->property_set,id);
                    }
                }
            }
            else {
                /* empty header -> exit */
                result = TRUE;
                break;
            }
        }
    }
    while(apt_text_is_eos(text_stream) == FALSE);

    return result;
}
コード例 #3
0
ファイル: mrcp_message.c プロジェクト: Jared-Prime/UniMRCP
/** Parse MRCP message-header */
MRCP_DECLARE(apt_bool_t) mrcp_message_header_parse(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	apt_pair_t pair;
	apt_bool_t result = FALSE;

	mrcp_header_allocate(&message_header->generic_header_accessor,pool);
	mrcp_header_allocate(&message_header->resource_header_accessor,pool);

	do {
		if(apt_text_header_read(text_stream,&pair) == TRUE) {
			if(pair.name.length) {
				/* normal header */
				if(mrcp_header_parse(&message_header->resource_header_accessor,&pair,pool) != TRUE) {
					if(mrcp_header_parse(&message_header->generic_header_accessor,&pair,pool) != TRUE) {
						/* unknown MRCP header */
					}
				}
			}
			else {
				/* empty header -> exit */
				result = TRUE;
				break;
			}
		}
		else {
			/* malformed header, skip to the next one */
		}
	}
	while(apt_text_is_eos(text_stream) == FALSE);

	return result;
}
コード例 #4
0
/* Receive MRCP message through TCP/MRCPv2 connection */
static apt_bool_t mrcp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
{
	mrcp_connection_agent_t *agent = obj;
	mrcp_connection_t *connection = descriptor->client_data;
	apr_status_t status;
	apr_size_t offset;
	apr_size_t length;
	apt_text_stream_t *stream;
	mrcp_message_t *message;
	apt_message_status_e msg_status;

	if(!connection || !connection->sock) {
		return FALSE;
	}
	stream = &connection->rx_stream;

	/* calculate offset remaining from the previous receive / if any */
	offset = stream->pos - stream->text.buf;
	/* calculate available length */
	length = connection->rx_buffer_size - offset;

	status = apr_socket_recv(connection->sock,stream->pos,&length);
	if(status == APR_EOF || length == 0) {
		apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP/MRCPv2 Peer Disconnected %s",connection->id);
		if(pollset) {
			apt_pollset_remove(pollset,&connection->sock_pfd);
		}
		apr_socket_close(connection->sock);
		connection->sock = NULL;

		mrcp_client_agent_disconnect_raise(agent,connection);
		return TRUE;
	}
	
	/* calculate actual length of the stream */
	stream->text.length = offset + length;
	stream->pos[length] = '\0';
	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s",
			connection->id,
			length,
			connection->verbose == TRUE ? length : 0,
			stream->pos);

	/* reset pos */
	apt_text_stream_reset(stream);

	do {
		msg_status = mrcp_parser_run(connection->parser,stream,&message);
		if(mrcp_client_message_handler(connection,message,msg_status) == FALSE) {
			return FALSE;
		}
	}
	while(apt_text_is_eos(stream) == FALSE);

	/* scroll remaining stream */
	apt_text_stream_scroll(stream);
	return TRUE;
}
コード例 #5
0
static apt_message_status_e apt_message_generator_break(apt_message_generator_t *generator, apt_text_stream_t *stream)
{
	/* failed to generate message */
	if(apt_text_is_eos(stream) == TRUE) {
		/* end of stream reached */
		return APT_MESSAGE_STATUS_INCOMPLETE;
	}

	/* error case */
	return APT_MESSAGE_STATUS_INVALID;
}
コード例 #6
0
static apt_bool_t test_file_process(apt_test_suite_t *suite, const char *file_path)
{
	apr_file_t *file;
	char buffer[500];
	apt_text_stream_t stream;
	rtsp_parser_t *parser;
	rtsp_generator_t *generator;
	apr_size_t length;
	apr_size_t offset;
	rtsp_message_t *message;
	apt_message_status_e msg_status;

	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open File [%s]",file_path);
	if(apr_file_open(&file,file_path,APR_FOPEN_READ | APR_FOPEN_BINARY,APR_OS_DEFAULT,suite->pool) != APR_SUCCESS) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open File");
		return FALSE;
	}

	parser = rtsp_parser_create(suite->pool);
	generator = rtsp_generator_create(suite->pool);

	apt_text_stream_init(&stream,buffer,sizeof(buffer)-1);

	do {
		/* calculate offset remaining from the previous receive / if any */
		offset = stream.pos - stream.text.buf;
		/* calculate available length */
		length = sizeof(buffer) - 1 - offset;

		if(apr_file_read(file,stream.pos,&length) != APR_SUCCESS) {
			break;
		}
		/* calculate actual length of the stream */
		stream.text.length = offset + length;
		stream.pos[length] = '\0';
		apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Parse RTSP Stream [%"APR_SIZE_T_FMT" bytes]\n%s",length,stream.pos);
		
		/* reset pos */
		apt_text_stream_reset(&stream);
		
		do {
			msg_status = rtsp_parser_run(parser,&stream,&message);
			rtsp_message_handler(generator,message,msg_status);
		}
		while(apt_text_is_eos(&stream) == FALSE);

		/* scroll remaining stream */
		apt_text_stream_scroll(&stream);
	}
	while(apr_file_eof(file) != APR_EOF);

	apr_file_close(file);
	return TRUE;
}
コード例 #7
0
ファイル: rtsp_server.c プロジェクト: unispeech/unimrcp
/* Receive RTSP message through RTSP connection */
static apt_bool_t rtsp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
{
	rtsp_server_t *server = obj;
	rtsp_server_connection_t *rtsp_connection = descriptor->client_data;
	apr_status_t status;
	apr_size_t offset;
	apr_size_t length;
	apt_text_stream_t *stream;
	rtsp_message_t *message;
	apt_message_status_e msg_status;

	if(descriptor->desc.s == server->listen_sock) {
		apt_log(RTSP_LOG_MARK,APT_PRIO_DEBUG,"Accept Connection");
		return rtsp_server_connection_accept(server);
	}
	
	if(!rtsp_connection || !rtsp_connection->sock) {
		return FALSE;
	}
	stream = &rtsp_connection->rx_stream;

	/* calculate offset remaining from the previous receive / if any */
	offset = stream->pos - stream->text.buf;
	/* calculate available length */
	length = sizeof(rtsp_connection->rx_buffer) - 1 - offset;

	status = apr_socket_recv(rtsp_connection->sock,stream->pos,&length);
	if(status == APR_EOF || length == 0) {
		apt_log(RTSP_LOG_MARK,APT_PRIO_INFO,"RTSP Peer Disconnected %s",rtsp_connection->id);
		return rtsp_server_connection_close(server,rtsp_connection);
	}

	/* calculate actual length of the stream */
	stream->text.length = offset + length;
	stream->pos[length] = '\0';
	apt_log(RTSP_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Data %s [%"APR_SIZE_T_FMT" bytes]\n%s",
		rtsp_connection->id,
		length,
		stream->pos);

	/* reset pos */
	apt_text_stream_reset(stream);

	do {
		msg_status = rtsp_parser_run(rtsp_connection->parser,stream,&message);
		rtsp_server_message_handler(rtsp_connection,message,msg_status);
	}
	while(apt_text_is_eos(stream) == FALSE);

	/* scroll remaining stream */
	apt_text_stream_scroll(stream);
	return TRUE;
}
コード例 #8
0
ファイル: mrcp_stream.c プロジェクト: Jared-Prime/UniMRCP
static mrcp_stream_result_e mrcp_generator_break(mrcp_generator_t *generator, apt_text_stream_t *stream)
{
	/* failed to generate either start-line or header */
	if(apt_text_is_eos(stream) == TRUE) {
		/* end of stream reached, rewind/restore stream */
		stream->pos = generator->pos;
		generator->result = MRCP_STREAM_MESSAGE_TRUNCATED;
	}
	else {
		/* error case */
		generator->result = MRCP_STREAM_MESSAGE_INVALID;
	}
	return generator->result;
}
コード例 #9
0
ファイル: mrcp_stream.c プロジェクト: Jared-Prime/UniMRCP
static mrcp_stream_result_e mrcp_parser_break(mrcp_parser_t *parser, apt_text_stream_t *stream)
{
	/* failed to parse either start-line or header */
	if(apt_text_is_eos(stream) == TRUE) {
		/* end of stream reached, rewind/restore stream */
		stream->pos = parser->pos;
		parser->result = MRCP_STREAM_MESSAGE_TRUNCATED;
		parser->message = NULL;
	}
	else {
		/* error case */
		parser->result = MRCP_STREAM_MESSAGE_INVALID;
	}
	return parser->result;
}
コード例 #10
0
ファイル: mrcp_stream.c プロジェクト: Jared-Prime/UniMRCP
/** Walk through MRCP stream and invoke message handler for each parsed message */
MRCP_DECLARE(apt_bool_t) mrcp_stream_walk(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_handler_f handler, void *obj)
{
	mrcp_stream_result_e result;
	if(parser->skip_lf == TRUE) {
		/* skip <LF> occurred as a result of message segmentation between <CR> and <LF> */
		apt_text_char_skip(stream,APT_TOKEN_LF);
		parser->skip_lf = FALSE;
	}
	do {
		result = mrcp_parser_run(parser,stream);
		if(result == MRCP_STREAM_MESSAGE_COMPLETE) {
			/* message is completely parsed */
			apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Parsed MRCP Message [%lu]", stream->pos - stream->text.buf);
			/* invoke message handler */
			handler(obj,parser->message,result);
		}
		else if(result == MRCP_STREAM_MESSAGE_TRUNCATED) {
			/* message is partially parsed, to be continued */
			apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Truncated MRCP Message [%lu]", stream->pos - stream->text.buf);
			/* prepare stream for further processing */
			if(apt_text_stream_scroll(stream) == TRUE) {
				apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Scroll MRCP Stream", stream->text.buf);
			}
			return TRUE;
		}
		else if(result == MRCP_STREAM_MESSAGE_INVALID){
			/* error case */
			apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse MRCP Message");
			/* invoke message handler */
			handler(obj,parser->message,result);
			/* reset stream pos */
			stream->pos = stream->text.buf;
			return FALSE;
		}
	}
	while(apt_text_is_eos(stream) == FALSE);

	/* reset stream pos */
	stream->pos = stream->text.buf;
	return TRUE;
}
コード例 #11
0
ファイル: mrcp_message.c プロジェクト: Jared-Prime/UniMRCP
/** Parse MRCP channel-identifier */
MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	apt_bool_t match = FALSE;
	apt_pair_t pair;
	do {
		if(apt_text_header_read(text_stream,&pair) == TRUE) {
			if(pair.name.length) {
				if(pair.value.length && strncasecmp(pair.name.buf,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH) == 0) {
					match = TRUE;
					apt_id_resource_parse(&pair.value,'@',&channel_id->session_id,&channel_id->resource_name,pool);
					break;
				}
				/* skip this header, expecting channel identifier first */
			}
			else {
				/* empty header */
				break;
			}
		}
	}
	while(apt_text_is_eos(text_stream) == FALSE);
	return match;
}
コード例 #12
0
/** Parse message by raising corresponding event handlers */
APT_DECLARE(apt_message_status_e) apt_message_parser_run(apt_message_parser_t *parser, apt_text_stream_t *stream, void **message)
{
	const char *pos;
	apt_message_status_e status = APT_MESSAGE_STATUS_INCOMPLETE;
	if(parser->skip_lf == TRUE) {
		/* skip <LF> occurred as a result of message segmentation between <CR> and <LF> */
		apt_text_char_skip(stream,APT_TOKEN_LF);
		parser->skip_lf = FALSE;
	}
	if(message) {
		*message = NULL;
	}

	do {
		pos = stream->pos;
		if(parser->stage == APT_MESSAGE_STAGE_START_LINE) {
			if(parser->vtable->on_start(parser,&parser->context,stream,parser->pool) == FALSE) {
				if(apt_text_is_eos(stream) == FALSE) {
					status = APT_MESSAGE_STATUS_INVALID;
				}
				break;
			}
			
			apt_crlf_segmentation_test(parser,stream);

			parser->stage = APT_MESSAGE_STAGE_HEADER;
		}

		if(parser->stage == APT_MESSAGE_STAGE_HEADER) {
			/* read header section */
			apt_bool_t res = apt_header_section_parse(parser->context.header,stream,parser->pool);
			if(parser->verbose == TRUE) {
				apr_size_t length = stream->pos - pos;
				apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Parsed Message Header [%"APR_SIZE_T_FMT" bytes]\n%.*s",
						length, length, pos);
			}
			
			apt_crlf_segmentation_test(parser,stream);

			if(res == FALSE) {
				break;
			}

			if(parser->vtable->on_header_complete) {
				if(parser->vtable->on_header_complete(parser,&parser->context) == FALSE) {
					status = APT_MESSAGE_STATUS_INVALID;
					break;
				}
			}
			
			if(parser->context.body && parser->context.body->length) {
				apt_str_t *body = parser->context.body;
				parser->content_length = body->length;
				body->buf = apr_palloc(parser->pool,parser->content_length+1);
				body->buf[parser->content_length] = '\0';
				body->length = 0;
				parser->stage = APT_MESSAGE_STAGE_BODY;
			}
			else {
				status = APT_MESSAGE_STATUS_COMPLETE;
				if(message) {
					*message = parser->context.message;
				}
				parser->stage = APT_MESSAGE_STAGE_START_LINE;
				break;
			}
		}

		if(parser->stage == APT_MESSAGE_STAGE_BODY) {
			if(apt_message_body_read(parser,stream) == FALSE) {
				break;
			}
			
			if(parser->vtable->on_body_complete) {
				parser->vtable->on_body_complete(parser,&parser->context);
			}
			status = APT_MESSAGE_STATUS_COMPLETE;
			if(message) {
				*message = parser->context.message;
			}
			parser->stage = APT_MESSAGE_STAGE_START_LINE;
			break;
		}
	}
	while(apt_text_is_eos(stream) == FALSE);

	return status;
}
コード例 #13
0
/** Get the next content part */
APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_content_part_t *content_part, apt_bool_t *is_final)
{
	apt_str_t boundary;
	apt_header_field_t *header_field;
	apt_text_stream_t *stream = &multipart_content->stream;

	if(!content_part || !is_final) {
		return FALSE;
	}
	*is_final = FALSE;
	apt_content_part_reset(content_part);

	/* skip preamble */
	apt_text_skip_to_char(stream,'-');
	if(apt_text_is_eos(stream) == TRUE) {
		return FALSE;
	}

	/* skip initial hyphens */
	apt_text_chars_skip(stream,'-');
	if(apt_text_is_eos(stream) == TRUE) {
		return FALSE;
	}

	/* read line and the boundary */
	if(apt_text_line_read(stream,&boundary) == FALSE) {
		return FALSE;
	}

	/* remove optional trailing spaces */
	while(boundary.length && boundary.buf[boundary.length-1] == APT_TOKEN_SP) boundary.length--;

	/* check whether this is the final boundary */
	if(boundary.length >= 2) {
		if(boundary.buf[boundary.length-1] == '-' && boundary.buf[boundary.length-2] == '-') {
			/* final boundary */
			boundary.length -= 2;
			*is_final = TRUE;
		}
	}

	/* compare boundaries */
	if(apt_string_is_empty(&multipart_content->boundary) == TRUE) {
		/* no boundary was specified from user space, 
		learn boundary from the content */
		multipart_content->boundary = boundary;
	}
	else {
		if(apt_string_compare(&multipart_content->boundary,&boundary) == FALSE) {
			/* invalid boundary */
			return FALSE;
		}
	}

	if(*is_final == TRUE) {
		/* final boundary => return TRUE, content remains empty */
		return TRUE;
	}

	/* read header fields */
	if(apt_header_section_parse(&content_part->header,stream,multipart_content->pool) == FALSE) {
		return FALSE;
	}
	
	for(header_field = APR_RING_FIRST(&content_part->header.ring);
			header_field != APR_RING_SENTINEL(&content_part->header.ring, apt_header_field_t, link);
				header_field = APR_RING_NEXT(header_field, link)) {
		if(strncmp(header_field->name.buf,CONTENT_LENGTH_HEADER,header_field->name.length) == 0) {
			content_part->length = &header_field->value;
		}
		else if(strncmp(header_field->name.buf,CONTENT_TYPE_HEADER,header_field->name.length) == 0) {
			content_part->type = &header_field->value;
		}
		else if(strncmp(header_field->name.buf,CONTENT_ID_HEADER,header_field->name.length) == 0) {
			content_part->id = &header_field->value;
		}
	}

	if(content_part->length && apt_string_is_empty(content_part->length) == FALSE) {
		apr_size_t length = atoi(content_part->length->buf);
		if(length + stream->pos > stream->end) {
			return FALSE;
		}

		/* read content */
		apt_string_assign_n(&content_part->body,stream->pos,length,multipart_content->pool);
		stream->pos += length;
	}

	return TRUE;
}
コード例 #14
0
/** Get the next content part */
APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_str_t *content_type, apt_str_t *content)
{
	apt_str_t boundary;
	apt_pair_t header;
	apt_bool_t is_final = FALSE;
	apt_text_stream_t *stream = &multipart_content->stream;

	if(!content || !content_type) {
		return FALSE;
	}

	apt_string_reset(content);

	/* skip preamble */
	apt_text_skip_to_char(stream,'-');
	if(apt_text_is_eos(stream) == TRUE) {
		return FALSE;
	}

	/* skip initial hyphens */
	apt_text_chars_skip(stream,'-');
	if(apt_text_is_eos(stream) == TRUE) {
		return FALSE;
	}

	/* read line and the boundary */
	if(apt_text_line_read(stream,&boundary) == FALSE) {
		return FALSE;
	}

	/* remove optional trailing spaces */
	while(boundary.length && boundary.buf[boundary.length-1] == APT_TOKEN_SP) boundary.length--;

	/* check whether this is the final boundary */
	if(boundary.length >= 2) {
		if(boundary.buf[boundary.length-1] == '-' && boundary.buf[boundary.length-2] == '-') {
			/* final boundary */
			boundary.length -= 2;
			is_final = TRUE;
		}
	}

	/* compare boundaries */
	if(apt_string_is_empty(&multipart_content->boundary) == TRUE) {
		/* no boundary was specified from user space, 
		learn boundary from the content */
		multipart_content->boundary = boundary;
	}
	else {
		if(apt_string_compare(&multipart_content->boundary,&boundary) == FALSE) {
			/* invalid boundary */
			return FALSE;
		}
	}

	if(is_final == TRUE) {
		/* final boundary => return TRUE, content remains empty */
		return TRUE;
	}

	/* read header fields */
	do {
		if(apt_text_header_read(stream,&header) == TRUE) {
			if(header.name.length) {
				if(apt_string_compare(&multipart_content->content_type_header,&header.name) == TRUE) {
					apt_string_copy(content_type,&header.value,multipart_content->pool);
				}
				else if(apt_string_compare(&multipart_content->content_length_header,&header.name) == TRUE) {
					if(header.value.buf) {
						content->length = atol(header.value.buf);
						if(content->length) {
							content->buf = apr_palloc(multipart_content->pool,content->length+1);
							content->buf[content->length] = '\0';
						}
					}
				}
			}
			else {
				/* empty header => exit */
				break;
			}
		}
	}
	while(apt_text_is_eos(stream) == FALSE);

	if(!content->length || content->length + stream->pos > stream->end) {
		return FALSE;
	}

	/* read content */
	memcpy(content->buf,stream->pos,content->length);
	stream->pos += content->length;
	return TRUE;
}