freeswitch mrcp 源码分析--数据解析

来源:互联网 发布:java范例开发大全 pdf 编辑:程序博客网 时间:2024/06/05 11:27



/** 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;}

首先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}
};


原创粉丝点击