/** 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
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;
}
首先apt_message_parser_run中首先调用
parser->vtable->on_start(parser,&parser->context,stream,parser->pool)
解析第一行,然后调用
parser->vtable->on_header_complete(parser,&parser->context)
解析其他部分。
这里vtable是一个apt_message_parser_vtable_t对象,他被初始化为:
static const apt_message_parser_vtable_t parser_vtable = {
mrcp_parser_on_start,
mrcp_parser_on_header_complete,
NULL
};
所以实际上他分别调用的是mrcp_parser_on_start()和mrcp_parser_on_header_complete()
/** Parse MRCP start-line */
MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_str_t *str, apr_pool_t *pool)
{
apt_text_stream_t line;
apt_str_t field;
apt_bool_t status = TRUE;
start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
apt_text_stream_init(&line,str->buf,str->length);
if(apt_text_field_read(&line,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot read the first field in start-line");
return FALSE;
}
if(field.buf == strstr(field.buf,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_LOG_MARK,APT_PRIO_WARNING,"Unknown MRCP version");
return FALSE;
}
}
else {
/* parsing MRCP v1 request or event */
apt_string_copy(&start_line->method_name,&field,pool);
status = mrcp_request_line_parse(start_line,&line);
}
return status;
}
在mrcp_start_line_parse()中先调用mrcp_version_parse()解析得到使用的MRCP的版本号,对于V2的显然会调用mrcp_v2_start_line_parse()做进一步的解析。
/** Parse MRCP v2 start-line */
static apt_bool_t mrcp_v2_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream, apr_pool_t *pool)
{
apt_str_t field;
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse message-length in v2 start-line");
return FALSE;
}
start_line->length = apt_size_value_parse(&field);
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse request-id in v2 start-line");
return FALSE;
}
start_line->request_id = mrcp_request_id_parse(&field);
if(start_line->request_id == 0 && *field.buf != '0') {
/* parsing MRCP v2 request or event */
start_line->message_type = MRCP_MESSAGE_TYPE_REQUEST;
apt_string_copy(&start_line->method_name,&field,pool);
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse request-id in v2 start-line");
return FALSE;
}
start_line->request_id = mrcp_request_id_parse(&field);
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == TRUE) {
/* parsing MRCP v2 event */
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;
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse status-code in v2 start-line");
return FALSE;
}
start_line->status_code = mrcp_status_code_parse(&field);
if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse request-state in v2 start-line");
return FALSE;
}
start_line->request_state = mrcp_request_state_parse(&field);
}
return TRUE;
}
接着,调用mrcp_start_line的mrcp_v2_start_line_parse()函数解析第一行文本MRCP/2.0后的内容:
MRCP/2.0 689 RECOGNITION-COMPLETE 9 COMPLETE
首先调用apt_size_value_parse()获取数据长度也就是 689。然后调用mrcp_request_id_parse()获取request_id,这里有个坑,因为下一个是RECOGNITION-COMPLETE,他不是数字,所以获取id失败会返回0。所以接下来会执行apt_string_copy(&start_line->method_name,&field,pool);将RECOGNITION-COMPLETE 赋值给start_line->method_name。这个变量在后面会起到非常重要的作用。
然后调用mrcp_request_id_parse解析request_id。最后调用mrcp_request_state_parse得到状态。
/** Header section handler */
static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context)
{
mrcp_message_t *mrcp_message = context->message;
if(mrcp_message->start_line.version == MRCP_VERSION_2) {
mrcp_resource_t *resource;
mrcp_parser_t *mrcp_parser;
if(mrcp_channel_id_parse(&mrcp_message->channel_id,&mrcp_message->header,mrcp_message->pool) == FALSE) {
return FALSE;
}
mrcp_parser = apt_message_parser_object_get(parser);
/* find resource */
resource = mrcp_resource_find(mrcp_parser->resource_factory,&mrcp_message->channel_id.resource_name);
if(!resource) {
return FALSE;
}
if(mrcp_message_resource_set(mrcp_message,resource) == FALSE) {
return FALSE;
}
}
if(mrcp_header_fields_parse(&mrcp_message->header,mrcp_message->pool) == FALSE) {
return FALSE;
}
if(context->body && mrcp_generic_header_property_check(mrcp_message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
mrcp_generic_header_t *generic_header = mrcp_generic_header_get(mrcp_message);
if(generic_header && generic_header->content_length) {
context->body->length = generic_header->content_length;
}
}
return TRUE;
}
在mrcp_parser_on_header_complete中首相调用mrcp_channel_id_parse()解析通道号。
Channel-Identifier: b4f5e73a39b84816@speechrecog
然后调用mrcp_resource_find()找到通道对应的资源。
进而调用mrcp_message_resource_set()
/** Associate MRCP resource specific data by resource name */
MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, const mrcp_resource_t *resource)
{
if(!resource) {
return FALSE;
}
message->resource = resource;
mrcp_message_header_data_alloc(
&message->header,
mrcp_generic_header_vtable_get(message->start_line.version),
resource->get_resource_header_vtable(message->start_line.version),
message->pool);
/* associate method_name and method_id */
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
message->start_line.method_id = apt_string_table_id_find(
resource->get_method_str_table(message->start_line.version),
resource->method_count,
&message->start_line.method_name);
if(message->start_line.method_id >= resource->method_count) {
return FALSE;
}
}
else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
message->start_line.method_id = apt_string_table_id_find(
resource->get_event_str_table(message->start_line.version),
resource->event_count,
&message->start_line.method_name);
if(message->start_line.method_id >= resource->event_count) {
return FALSE;
}
}
return TRUE;
}
找到事件对应的方法ID, 并设置给:message->start_line.method_id。这里resource->get_event_str_table(message->start_line.version)返回的就是:
/** String table of MRCPv2 recognizer events (mrcp_recognizer_event_id) */
static const apt_str_table_item_t v2_recog_event_string_table[] = {
{{"START-OF-INPUT", 14},0},
{{"RECOGNITION-COMPLETE", 20},0},
{{"INTERPRETATION-COMPLETE", 23},0}
};
————————————————
版权声明:本文为CSDN博主「罗自荣」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/luozirong/article/details/78857016